-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Speed up bind_self() in trivial cases #19024
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
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
Hm, the little |
This comment has been minimized.
This comment has been minimized.
OK, that didn't go well. I guess it would be easier to just bake out this part of the optimization, most likely it is minor compared to the other part. |
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
@@ -1420,5 +1458,45 @@ def analyze_decorator_or_funcbase_access( | |||
if isinstance(defn, Decorator): | |||
return analyze_var(name, defn.var, itype, mx) | |||
typ = function_type(defn, mx.chk.named_type("builtins.function")) | |||
is_trivial_self = False |
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.
Would it make sense to introduce an interface implemented by Decorator
and FuncBase
and put an is_trivial_self()
property/method there? I remember seeing similar decorator/func ladders for other reasons too, so such refactoring won't be wasted - they should have some common properties, after all. (and this block is already copy-pasted twice)
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.
Yeah, I was not sure about this, ultimately I decided to save some microseconds by "inlining" it.
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.
Would you mind me profiling this difference (inline vs shared interface) tomorrow? I wanted to figure out how to profile mypyc-compiled code reliably, sounds like a good chance. (Anyway this isn't blocking, this part can be refactored separately later - perhaps together with some other "shared" methods)
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 definitely can't stop you, but I guess this may be tricky, as difference is likely small.
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.
Likely non-existent when running, say, whole self-check, but easy to microbenchmark! (but probably it'd be better to profile some reasonable refactoring attempt instead)
Anyway, after baking out the second part, I still see >3% performance improvement. |
See #18991 for context.
We can skip all of logic in
check_self_arg()
and 90% of logic inbind_self()
for methods with trivialself
/cls
(i.e. if first argument has no explicit annotation and there is noSelf
in signature).Locally I see 3-4% performance improvement (for self-check with non-compiled mypy).