python / python/cpython

Constant-fold f-strings with constant fields in the CFG optimizer

Offen
#154,910 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

interpreter-core performance type-feature
Vorherrschende Sprache
Python
Sterne
77.2k
Forks
35.9k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Feature or enhancement

Proposal:

The flowgraph optimizer folds constant expressions in most positions (binary/unary ops, tuples of constants, in against literal collections), but f-strings whose fields are all constants are left unfolded:

>>> import dis
>>> dis.dis(lambda: f'{1}{2}')
   RESUME                   0
   LOAD_SMALL_INT           1
   FORMAT_SIMPLE
   LOAD_SMALL_INT           2
   FORMAT_SIMPLE
   BUILD_STRING             2
   RETURN_VALUE

This could compile to a single LOAD_CONST '12', the same way '1' + '2' already does.

The transformation is safe under a narrow guard:

  • FORMAT_SIMPLE on an operand that is an exact str, int, float or bool constant is pure and calls no user code (subclasses can override __format__/__str__, so exact-type checks are required).
  • FORMAT_WITH_SPEC with a constant spec on those exact types is pure for the same reason, though it could be left to a follow-up.
  • BUILD_STRING over constant strings is pure.

Conversion functions (!r, !s, !a) lower to intrinsics before FORMAT_SIMPLE, so f'{1!r}' is out of scope unless the intrinsic is also handled; the initial change can simply not match those sequences.

Constant fields do appear in real code — mixed f-strings like f'{HEADER}{x}' gain partially (the constant fields fold, shrinking BUILD_STRING's operand count), and fully-constant f-strings show up in generated code and in string-building via comprehensions.

The natural place is a fold_format_simple alongside fold_tuple_of_constants in Python/flowgraph.c, using the existing get_const_loading_instrs / instr_make_load_const helpers.

gh-77273 covered the opcode-level inefficiency of f-string formatting and was resolved by the FORMAT_SIMPLE/FORMAT_WITH_SPEC redesign; this proposal is about folding the constant cases of those opcodes, which is not currently done anywhere in the compiler.

With a prototype of the fold, a fully-constant f-string costs the same as the equivalent string literal (~34 ns/call instead of ~1770 ns/call on a debug free-threaded build — I'll post release-build pyperf numbers on the PR). I have a patch ready and will follow up with it.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs
  • gh-154911

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne in Python/flowgraph.c neben fold_tuple_of_constants und überprüfe get_const_loading_instrs und instr_make_load_const. Verifiziere, dass der Optimizer geeignete Sequenzen konstanter FORMAT_SIMPLE- und BUILD_STRING-Anweisungen verarbeitet, während Konvertierungen und nicht-exakte Typen unverändert bleiben, und vergleiche anschließend den generierten Bytecode und die Performance mit dem verknüpften PR gh-154911.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.