python / python/cpython

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

Ouverte
#154,910 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

interpreter-core performance type-feature
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

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

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez dans Python/flowgraph.c à côté de fold_tuple_of_constants, et examinez get_const_loading_instrs et instr_make_load_const. Vérifiez que l’optimiseur gère les séquences éligibles de FORMAT_SIMPLE et BUILD_STRING constants tout en laissant les conversions et les types non exacts inchangés, puis comparez le bytecode généré et les performances avec le PR lié gh-154911.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
compilers
Type d'issue
Fonctionnalité
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
25/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.