Title: gh-74690: typing: Don't unnecessarily call `_get_protocol_attrs` twice in `_ProtocolMeta.__instancecheck__` by AlexWaygood · Pull Request #103141 · python/cpython · GitHub
Open Graph Title: gh-74690: typing: Don't unnecessarily call `_get_protocol_attrs` twice in `_ProtocolMeta.__instancecheck__` by AlexWaygood · Pull Request #103141 · python/cpython
X Title: gh-74690: typing: Don't unnecessarily call `_get_protocol_attrs` twice in `_ProtocolMeta.__instancecheck__` by AlexWaygood · Pull Request #103141 · python/cpython
Description: This simple optimisation achieves speedups for all kinds of isinstance() checks against runtime-checkable protocols. For structural subtypes that set attributes in __init__ methods, the speedup is dramatic. Benchmark script import time from typing import Protocol, runtime_checkable @runtime_checkable class HasX(Protocol): x: int class Foo: @property def x(self) -> int: return 42 class Bar: x = 42 class Baz: def __init__(self): self.x = 42 class Egg: ... class Nominal(HasX): def __init__(self): self.x = 42 class Registered: ... HasX.register(Registered) num_instances = 500_000 foos = [Foo() for _ in range(num_instances)] bars = [Bar() for _ in range(num_instances)] bazzes = [Baz() for _ in range(num_instances)] basket = [Egg() for _ in range(num_instances)] nominals = [Nominal() for _ in range(num_instances)] registereds = [Registered() for _ in range(num_instances)] def bench(objs, title): start_time = time.perf_counter() for obj in objs: isinstance(obj, HasX) elapsed = time.perf_counter() - start_time print(f"{title}: {elapsed:.2f}") bench(foos, "Time taken for objects with a property") bench(bars, "Time taken for objects with a classvar") bench(bazzes, "Time taken for objects with an instance var") bench(basket, "Time taken for objects with no var") bench(nominals, "Time taken for nominal subclass instances") bench(registereds, "Time taken for registered subclass instances") Results on 01a49d1 (non-debug build, PGO-optimised): Time taken for objects with a property: 3.63 Time taken for objects with a classvar: 3.82 Time taken for objects with an instance var: 12.22 Time taken for objects with no var: 13.73 Time taken for nominal subclass instances: 12.46 Time taken for registered subclass instances: 20.62 Results with this PR: Time taken for objects with a property: 2.10 Time taken for objects with a classvar: 2.07 Time taken for objects with an instance var: 2.06 Time taken for objects with no var: 6.94 Time taken for nominal subclass instances: 7.54 Time taken for registered subclass instances: 16.06 (We may want to wait until #103034 is merged and then re-measure.) Cc. @leycec and @posita, as people who I know care a lot about Protocol performance :) Issue: gh-74690
Open Graph Description: This simple optimisation achieves speedups for all kinds of isinstance() checks against runtime-checkable protocols. For structural subtypes that set attributes in __init__ methods, the speedup is ...
X Description: This simple optimisation achieves speedups for all kinds of isinstance() checks against runtime-checkable protocols. For structural subtypes that set attributes in __init__ methods, the speedup is ...
Opengraph URL: https://github.com/python/cpython/pull/103141
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:8eda5c80-eca8-4042-0274-8ef3c98ecc3d |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | 962E:DEDFE:1444A53:1B1B631:696ADD67 |
| html-safe-nonce | 03dd55fd56b188fe4f341fe8e60b6897c46f85904cb7c24be20417506c35cd83 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NjJFOkRFREZFOjE0NDRBNTM6MUIxQjYzMTo2OTZBREQ2NyIsInZpc2l0b3JfaWQiOiI4MjAyODE4NTk4NzI4NDEwNjMiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | a8fe78a2d7d87361072c00d7949d164473cde781d88816a7a137b9b0805d3576 |
| hovercard-subject-tag | pull_request:1296952282 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/python/cpython/pull/103141/files |
| twitter:image | https://avatars.githubusercontent.com/u/66076021?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/66076021?s=400&v=4 |
| og:image:alt | This simple optimisation achieves speedups for all kinds of isinstance() checks against runtime-checkable protocols. For structural subtypes that set attributes in __init__ methods, the speedup is ... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f99f7c1d70f01da5b93e5ca90303359738944d8ab470e396496262c66e60b8d |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 524a93f2c1f36522a3b4be4c110467ee4172245d |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width