-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
[mypyc] Implement dict copy primitive #9721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0524209
to
2a4280d
Compare
It seems that a test case (
Any pointers as to why this could be happening? |
9e93f51
to
78f3590
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks Good! Thanks! Please wait for another round review from @JukkaL and this can be merged
Results from https://github.com/mypyc/mypyc-benchmarks: Master:
PR:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks! This is a nice performance improvement for a pretty common operation.
Left some suggestions to improve test coverage (they are recommended but not necessary).
mypyc/test-data/run-dicts.test
Outdated
d = {} | ||
assert d.copy() == d | ||
d = {'a': 1, 'b': 2} | ||
assert d.copy() == d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideas for additional checks:
- Test that the result is not the same object (
assert d.copy() is not d
). - Test that this works with
DefaultDict
objects when the annotated type isDict[...]
, to check for the non-exact code path here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some additional checks. Let me know if it looks ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed that these tests are in driver.py
, which doesn't get compiled, so these aren't actually testing anything useful. The recommended way of writing tests is to avoid driver.py
altogether so that everything gets compiled, in part because it's easy to accidentally have an essentially no-op test case. Unfortunately, most of the existing test cases use driver.py
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test code still needs to be moved away from driver.py
. It would probably be easier to create a new test case that doesn't define driver.py
at all (see the mypyc developer docs for how to do this).
61f3fd0
to
2bc1a82
Compare
mypyc/test-data/run-dicts.test
Outdated
d = {} | ||
assert d.copy() == d | ||
d = {'a': 1, 'b': 2} | ||
assert d.copy() == d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed that these tests are in driver.py
, which doesn't get compiled, so these aren't actually testing anything useful. The recommended way of writing tests is to avoid driver.py
altogether so that everything gets compiled, in part because it's easy to accidentally have an essentially no-op test case. Unfortunately, most of the existing test cases use driver.py
.
mypyc/test-data/run-dicts.test
Outdated
d = {} | ||
assert d.copy() == d | ||
d = {'a': 1, 'b': 2} | ||
assert d.copy() == d | ||
assert d.copy() is not d | ||
d = defaultdict(int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this will infer defaultdict
as the type, so the new primitive will not be used. Instead you can do something like this to override the inferred type:
dd: Dict[str, int] = defaultdict(int)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, would adding some functions for creating the dictionaries and copying them under something like [case testDictCopy]
and then calling those functions and using assert under driver.py
resolve this issue?
mypyc/test-data/run-dicts.test
Outdated
d = {} | ||
assert d.copy() == d | ||
d = {'a': 1, 'b': 2} | ||
assert d.copy() == d | ||
assert d.copy() is not d | ||
d = defaultdict(int) | ||
assert d.copy() == d |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a non-empty default dict instance, and check that the type of the return value is correct (assert isinstance(d.copy(), defaultdict)
.
mypyc/test-data/irbuild-dict.test
Outdated
[case testDictCopy] | ||
from typing import Dict | ||
def f(d: Dict[int, int]) -> Dict[int, int]: | ||
return d.copy() # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add copy()
to the test stubs in mypyc/test-data/fixtures/ir.py
and remove # type: ignore
afterwards? Using # type: ignore
can be problematic, as it can hide legitimate errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember encountering some issues when removing the # type: ignore
on CI that did not show up locally, so I ended up adding it as a temporary workaround. Removed it anyways and added copy()
on mypyc/test-data/fixtures/ir.py
mypyc/test-data/run-dicts.test
Outdated
assert d.copy() is not d # type: ignore | ||
dd: Dict[str, int] = defaultdict(int) | ||
dd['a'] = 1 | ||
assert dd.copy() == dd # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to get rid of these # type: ignore
comments as well (see above).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
@vsakkas Any followup on this? It's pretty close to be merged. |
@TH3CHARLie I'm really sorry for the delay! Things came up and I never got to work on this. Thanks for reminding me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good!
Please avoid using force-push next time, it will ruin the commit history and make review difficult
Implement dict copy primitive (python#9721)
Description
Implements dict copy primitive for improved performance.
Related ticket: mypyc/mypyc#644
Test Plan
Ensure that both copying an empty and an non-empty dict works as expected, meaning that the original and the copied dicts contain the same key-values.
Generated IR
The following script was used:
Master branch:
PR:
Performance
Sample script:
Master branch: 1.09x speedup
PR: 1.27x speedup