python-attrs / python-attrs/attrs

Performance Improvement for evolve function

Open
#1,145 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Performance
Dominant language
Python
Stars
5.8k
Forks
480
Avg merge
2h 15m
Merged PRs (30d)
2

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attrs evolve function and reproduce the issue's timeit comparison between evolve(a, a=2) and direct construction. Evaluate the proposed per-class function generation and argument handling against the reported performance difference; done means a documented improvement without changing evolve's behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
performance
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.