Files
org-roamings/20220501130626-python_peephole_optimization.org
2022-06-04 12:57:39 +02:00

3.4 KiB

Peephole optimization

Introduction

Lorsque du code python est exécuté, celui-ci est compilé en bytecode et enregistré dans des fichiers .pyc stockés dans les répertoires __pycache__. Ces fichiers .pyc contiennent une version optimisée et plus rapide du code.

L'objet code

L'objet compilé code:

  • Est accessible depuis l'attribut __code__ des fonctions,
  • Contient le bytecode et d'autres informations nécessaires à CPython pour son exécution, notamment :

    • co_consts : un tuple regroupant les constantes présentes dans la fonction,
    • co_varnames : un tuple regroupant le nom des variables locales utilisées par la fonction,
    • co_names : un tuple regroupant les noms non-locaux référencés dans le corps de la fonction.

L'optimisation Peephole

Durant la phase de transcription en bytecode, certaines données telles que les expressions numériques, strings et tuples sont optimisées et stockées dans des instruction bytecode.

Les expressions constantes

Les calculs numériques

Les expressions constantes telles que a = 30 * 8 * 70 sont optimisées.

Les chaines de caractères et tuples

Les strings dont la longueur <= 4096 et les tuples dont la longueur <= 256 sont optimisées, les autres, non.

Les membership tests

Les membership tests (opérateur in et not in) permettent de tester la présence d'une valeur dans des sequences. Durant la phase de transcription, Python convertit les objets mutables (list et set) en leur version non mutables:

  • Les lists en tuples,
  • Les sets en frozen sets
def toto():
    a = 30 * 8 * 7
    b = "TDS" * 3
    c = "T" * 4097
    d = (1, 2) * 5
    e = (10, ) * 257
    f = [101, 102] * 2
    print("Hello TDS !!!")

print(f'toto function constants: {toto.__code__.co_consts}')
print(f'toto fonction local variable names: {toto.__code__.co_varnames}')
print(f'toto fonction non-local names: {toto.__code__.co_names}')
toto function constants: (None, 1680, 'TDSTDSTDS', 'T', 4097, (1, 2, 1, 2, 1, 2, 1, 2, 1, 2), (10,), 257, 101, 102, 2, 'Hello TDS !!!')
toto fonction local variable names: ('a', 'b', 'c', 'd', 'e', 'f')
toto fonction non-local names: ('print',)

Commentaires :

  • 30 * 8 * 70 est une expression constante et a été évaluée à 16800 par le compilateur,
  • “TDS” * 3 est aussi une expression constante et sa longueur est <= 4096. Elle a été évaluée à TDSTDSTDS par le compilateur,
  • “T” * 4097, de longueur > 4096, n'est pas optimisée,
  • (1, 2) * 5 est une séquence dont la longueur est <= 256 (10). Elle a été évaluée et stockée comme le tuple (1,2,1,2,1,2,1,2,1,2).
  • (10,) * 257 de longueur > 256, n'est pas optimisée,
  • [101, 102] * 2 est une list (objet mutable) et n'a pas été optimisée.
def toto():
    for a in [10, 20, 30]:
        pass

def titi():
    for a in {40, 50, 60}:
        pass

print(f'toto function constants: {toto.__code__.co_consts}') 
print(f'titi function constants: {titi.__code__.co_consts}')
toto function constants: (None, (10, 20, 30))
titi function constants: (None, frozenset({40, 50, 60}))