Title: gh-97933: inline list/dict/set comprehensions by carljm · Pull Request #101441 · python/cpython · GitHub
Open Graph Title: gh-97933: inline list/dict/set comprehensions by carljm · Pull Request #101441 · python/cpython
X Title: gh-97933: inline list/dict/set comprehensions by carljm · Pull Request #101441 · python/cpython
Description: Closes #97933. In builds with --enable-optimizations: ➜ ./python -m pyperf timeit -s 'l = [1, 2, 3, 4, 5]' '[x for x in l]' --compare-to ../mainopt/python /home/carljm/build/mainopt/python: ..................... 200 ns +- 3 ns /home/carljm/build/ic2opt/python: ..................... 120 ns +- 2 ns Mean +- std dev: [/home/carljm/build/mainopt/python] 200 ns +- 3 ns -> [/home/carljm/build/ic2opt/python] 120 ns +- 2 ns: 1.67x faster Credit to @vladima for authoring the original version of this code in Cinder 3.8. The compiler approach is different in this version (so as to support inlining all comprehensions, regardless of name clashes); some of the symbol table changes remain the same. A couple implementation notes: We need a new opcode LOAD_FAST_AND_CLEAR because we need to push/pop the value of possibly-undefined variables on the stack while clearing them. To do this with existing opcodes would require eliminating the invariant/assert that LOAD_FAST never loads NULL, and would add inefficient refcount operations and interpreter loop cycles. If a comprehension iteration variable is a cell inside the comprehension (i.e. the comprehension builds closures) we end up including that variable in both co_varnames and co_cellvars for the inlined-into outer function and using the non-offset (varnames) storage location for it. This is how function arguments that are also cells are currently handled, so we just piggyback on that handling. This makes the needed push/pop of the outer cell simpler as we can just use LOAD_FAST_AND_CLEAR/STORE_FAST as-is for it, and it will push/pop the cell itself. Otherwise we would need some new handling in the compiler for allowing push/pop of a cell in offset storage. This PR also adds a lot of new tests for comprehension scoping edge cases, and runs all new and existing scoping tests in module, function, and class scopes (without requiring duplication of the test code.) All comprehension scoping tests added in this diff also pass with comprehension inlining disabled (ensuring semantics did not change.) Issue: gh-97933
Open Graph Description: Closes #97933. In builds with --enable-optimizations: ➜ ./python -m pyperf timeit -s 'l = [1, 2, 3, 4, 5]' '[x for x in l]' --compare-to ../mainopt/python /home/carljm/build/mainopt...
X Description: Closes #97933. In builds with --enable-optimizations: ➜ ./python -m pyperf timeit -s 'l = [1, 2, 3, 4, 5]' '[x for x in l]' --compare-to ../mainopt/python /home/carl...
Opengraph URL: https://github.com/python/cpython/pull/101441
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/checks(.:format) |
| route-controller | pull_requests |
| route-action | checks |
| fetch-nonce | v2:af5f2a17-4a3d-e45a-be6b-deef02c48800 |
| current-catalog-service-hash | 87dc3bc62d9b466312751bfd5f889726f4f1337bdff4e8be7da7c93d6c00a25a |
| request-id | DE6C:2B81A2:19DE93:2329C6:6969CF06 |
| html-safe-nonce | 234b71b5d0980b0662f80f7c51bc8dee9f93b73cc6bfc9e4b45449698bb7e26c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJERTZDOjJCODFBMjoxOURFOTM6MjMyOUM2OjY5NjlDRjA2IiwidmlzaXRvcl9pZCI6IjQ4OTQ0NjM4MDY1MTYzNTA3MjYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 1730720e17c2f137a426867a9b7c0a8f14195973af26a0b7c6d791fdc19da145 |
| hovercard-subject-tag | pull_request:1222478346 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,checks,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/101441/checks |
| twitter:image | https://avatars.githubusercontent.com/u/61586?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/61586?s=400&v=4 |
| og:image:alt | Closes #97933. In builds with --enable-optimizations: ➜ ./python -m pyperf timeit -s 'l = [1, 2, 3, 4, 5]' '[x for x in l]' --compare-to ../mainopt/python /home/carljm/build/mainopt... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | acedec8b5f975d9e3d494ddd8f949b0b8a0de59d393901e26f73df9dcba80056 |
| turbo-cache-control | no-preview |
| 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 full-width full-width-p-0 |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 83c08c21cdda978090dc44364b71aa5bc6dcea79 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width