Skip to content

[mypyc] Specialize isinstance() with mixed and nested tuples - #22098

Open
rheard wants to merge 1 commit into
python:masterfrom
rheard:fix-mypyc-1227
Open

rheard wants to merge 1 commit into
python:masterfrom
rheard:fix-mypyc-1227

Conversation

@rheard

@rheard rheard commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Fixes mypyc/mypyc#1227

This is just an idea for how to improve performance, for an issue that was exposed to me because of the issues in PR #22097 .

isinstance(x, (A, B)) is specialized when every class in the tuple is a primitive type (#19949) or every class is a native class (mypyc/mypyc#413). Anything else falls back to the generic path, which builds a new tuple and calls PyObject_IsInstance on every call, so the primitive types in the tuple lose their fast checks as well. That covers:

  • a primitive type mixed with a native class: isinstance(x, (float, MyNativeClass))
  • a primitive type mixed with any other class: isinstance(x, (float, Decimal))
  • nested tuples, even when every class is a primitive type: isinstance(x, (int, (float, str)))

The chained checks added in #19949 could be generalized: flatten nested tuples, use the fast checks for primitive types and native classes, and check any other class with its own PyObject_IsInstance call, so no tuple is built. In a quick microbenchmark this takes isinstance(x, (float, MyNativeClass)) from about 50 ns to about 5 ns per call.

Relatedly, isinstance(f(), ()) currently returns False without calling f().

@ilevkivskyi

Copy link
Copy Markdown
Member

Thanks for all the mypyc PRs! I will probably leave them all to @JukkaL and @p-sawicki (or maybe I will take one-two if they are busy).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

isinstance() with a mixed or nested tuple builds a new tuple on every call

2 participants