:PROPERTIES: :ID: 26e1fdfb-1f8e-4c62-a08f-468a56ab03c8 :mtime: 20220501153548 :ctime: 20220501130626 :END: #+title: 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* #+BEGIN_SRC python :results output 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}') #+END_SRC #+RESULTS: : 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. #+BEGIN_SRC python :results output 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}') #+END_SRC #+RESULTS: : toto function constants: (None, (10, 20, 30)) : titi function constants: (None, frozenset({40, 50, 60}))