Optimize collection literals with leading null unpack idiom in bytecode, allows bare `BUILD_SET 0`
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 77.2k
- Fork
- 35.9k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Feature or enhancement
Proposal:
Performance was discussed at various times within PEP 802 topic, submitting this proposal as the PEP is unlikely to be accepted. This is intended as an advanced escape-hatch not overlapping with the main reasons for PEP 802.
Goal:
- Remove performance penalty of
ast.unparse(ast.Set(elts=[]))({*()}can be used in advanced cases and will not change recommended way to write empty setset()) - Remove performance penalty of incremental construction between 0-to-1/1-to-0 elements for
setandtupleliterals without special case considerations (e.g.x = *(),pre-seeded tuple literal without trailing comma pitfall) - Keep implementation simple/self-contained in bytecode generation, avoiding any AST changes to language
- Near-zero performance impact to bytecode generation (improves subsequent bytecode optimizations of target case)
Implementation examples:
- During first AST -> bytecode pass: https://github.com/python/cpython/commit/67742d92c411a93e7692f761ffeb3af75ba1ff87#diff-6d58b0ddc066ad12ebc378b62c4189335bd57c83aece11072c76fd86a78a1a4a
- During bytecode-only optimization step: https://github.com/python/cpython/commit/f857d88ef3aac90deadf438625211040e73df832#diff-3cbf15668c31488528b7ab0f903c674a0ecf550f4f53c1be6cf8cd965246c2a0
Micro-benchmark
Run on windows x64bit release build: empty_unpack_benchmark.py
Compile time
Targeted cases:
| Benchmark | Main | Flowgraph only | Codegen leading only |
|---|---|---|---|
[*()] |
1.450 ms / 1.000x | 1.393 ms / 0.961x | 1.378 ms / 0.950x |
{*()} |
1.530 ms / 1.000x | 1.488 ms / 0.973x | 1.467 ms / 0.959x |
(*(),) |
1.916 ms / 1.000x | 1.842 ms / 0.962x | 1.832 ms / 0.956x |
x = *(), |
1.139 ms / 1.000x | 1.088 ms / 0.955x | 1.055 ms / 0.927x |
xychart-beta
title "Compile targeted mean ratio vs main"
x-axis [Main, Flowgraph, Leading]
y-axis "Ratio" 0 --> 1.01
bar [1.000, 0.963, 0.948]
Control near-miss case comparisons moved less than +/-1% and are attributed to noise.
Runtime
The set() versus {*()} comparison is especially useful because it changes qualitatively across the two branches (~6.3% slower to ~29.5% faster):
| Branch | set() mean (ns) |
{*()} mean (ns) |
{*()} vs set() |
|---|---|---|---|
| Main | 54.14 | 57.53 | 1.063x |
| Flowgraph only | 53.49 | 38.01 | 0.711x |
| Codegen leading only | 55.44 | 39.00 | 0.704x |
Before this change, {*()} was paying for a redundant empty update and ended up slower than the constructor call. After the change, {*()} compiles down to a direct BUILD_SET 0; RETURN_VALUE path, while set() still has to load the global and perform a zero-argument call.
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/pep-802-display-syntax-for-the-empty-set/101676/237
https://discuss.python.org/t/pep-802-display-syntax-for-the-empty-set/101676/216
https://discuss.python.org/t/pep-802-display-syntax-for-the-empty-set/101676/3
Linked PRs
- gh-150812
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia esaminando empty_unpack_benchmark.py e gli esempi di implementazione collegati nella proposta, quindi esamina la PR collegata gh-150812 e la discussione correlata su Discourse. Il lavoro è completato quando i casi proposti di literal di collezione evitano aggiornamenti vuoti ridondanti, preservando al contempo il comportamento documentato e i miglioramenti dei benchmark.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- compilers
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 25/100