Skip to content

Performance Improvement for evolve function #1145

Open
@LukasKrocek

Description

@LukasKrocek

Hello,

I have been recently working with the evolve function in attrs and noticed some performance issues which I believe could be improved.

Here is an example I tried:

@frozen
class A:
    a: int
    b: str

a = A(1, "1")

print(timeit.timeit("evolve(a, a=2)", globals=globals()))  # 0.5601 seconds
print(timeit.timeit("A(2, a.b)", globals=globals()))  # 0.2004 seconds

The evolve function in this case appears to be almost three times slower than creating a new instance of the class manually.

Upon investigation, I discovered that a significant amount of time was spent on creating class Fields, iterating them, and updating unchanged values.

Additionally, I noticed that creating instances using kwargs took approximately 30% more time than using args:

print(timeit.timeit("A(a=2, b=a.b)", globals=globals())) # 0.2635 seconds

Given these findings, I suggest that we could improve the performance of the evolve function by generating per class functions the first time that the class is evolved. These functions would look something like this:

def evolve_A(inst, changes):
    return cls(
            changes.get("a", inst.a),
            changes.get("b", inst.b)
        )

I am open to creating a PR that would implement these changes if you think this is a good idea. I look forward to your thoughts on this.

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions