Skip to content

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

ilevkivskyi
Copy link
Member

@ilevkivskyi ilevkivskyi commented May 4, 2025

See #18991 for context.

We can skip all of logic in check_self_arg() and 90% of logic in bind_self() for methods with trivial self/cls (i.e. if first argument has no explicit annotation and there is no Self in signature).

Locally I see 3-4% performance improvement (for self-check with non-compiled mypy).

@ilevkivskyi ilevkivskyi requested a review from JukkaL May 4, 2025 12:59

This comment has been minimized.

@ilevkivskyi
Copy link
Member Author

Hm, the little mypy_primer fallout is caused by an edge case where "best-effort" filtering in bind_self() is actually more correct that the "proper" filtering in check_self_arg(). I will try to adjust the check in check_self_arg() now.

This comment has been minimized.

@ilevkivskyi
Copy link
Member Author

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.

Copy link
Contributor

github-actions bot commented May 4, 2025

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
Copy link
Collaborator

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)

Copy link
Member Author

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.

Copy link
Collaborator

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)

Copy link
Member Author

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.

Copy link
Collaborator

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)

@ilevkivskyi
Copy link
Member Author

Anyway, after baking out the second part, I still see >3% performance improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants