Uh oh!
There was an error while loading. Please reload this page.
gh-121192: Add fast path to deepcopy() for empty list/tuple/dict/set - #121193
gh-121192: Add fast path to deepcopy() for empty list/tuple/dict/set#121193lgeiger wants to merge 5 commits into
deepcopy() for empty list/tuple/dict/set#121193Conversation
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
d7b07eb to
d87901eCompareeendebakpt
commented
Jul 2, 2024
The optimization applied in the latest iteration of the PR is only applied when no memo is passed to The question then is whether a raises a results in |
eendebakpt
commented
Jul 2, 2024
For reference: I performed a benchmark of main, this PR and the deepcopy C implementation from #91610. On benchmark Results are |
sobolevn
commented
Jul 3, 2024
@eendebakpt it can happen for dataclass, example: fromdataclassesimportdataclass, as_dict@dataclassclassSome:
field: set[int]
as_dict(Some(set())) |
eendebakpt
commented
Jul 3, 2024
Indeed. Here a more complete example, including the cases where this PR helps |
lgeiger
commented
Jul 3, 2024
Thanks for the example! This PR indeed shows a decent improvement here: importpyperfrunner=pyperf.Runner()
setup="""from dataclasses import dataclass, asdict@dataclassclass Some: a: str t: tuple[int] field: set[int] # benefits l : list[int] d : dict[str, str] fs: frozenset[int] # benefits nonempty : set[int]s = Some('x', tuple(), set(), [], d={}, fs=frozenset(), nonempty={1, 2})"""runner.timeit(name="dataclass asdict", stmt=f"b = asdict(s)", setup=setup) |
sobolevn
commented
Jul 3, 2024
Other use-cases that we can find in our own code:
|
This PR is stale because it has been open for 30 days with no activity. |
eendebakpt
commented
Apr 17, 2026
I do not think the fast path is worth the case here. Better alternatives would be to create a C version of deepcopy or use an external package like https://github.com/percolab/copium. |
deepcopy()can be surprisingly slow when called with empty containers like lists, tuples, dicts, sets or frozensets.This adds a fast path for this case similar to #114266 which speeds up these cases by about 4x - 21x while having a small impact on the default path.
Here are some benchmarks comparing this PR against
main. Let me know if there are more benchmarks that I can run to verify that there a no performance regressions for the common case:deepcopy()for empty list/tuple/dict/set #121192