Detalles internos de rendimiento de Python y exabruptos sobre asyncio
Autor: Jesús Cea & Otros - Contacto: python2021@podcast.jcea.es
Fecha de grabación: 2021/01/05 - Duración: 01:56:42
Fecha de publicación: 2021/05/08
Palabras clave: Tertulia
Descarga el audio: M4A (28460808 bytes) - OPUS (14494498 bytes)
Participantes:
Jesús Cea, email: jcea@jcea.es, twitter: @jcea, https://blog.jcea.es/, https://www.jcea.es/. Conectando desde Madrid.
Eduardo Castro, email: info@ecdesign.es. Conectando desde A Guarda.
Javier, conectando desde Madrid.
Víctor Ramírez, twitter: @virako, programador python y amante de vim, conectando desde Huelva.
Juan Carlos, conectando desde Bilbao.
Audio editado por Pablo Gómez, twitter: @julebek.
La música de la entrada y la salida es "Lightning Bugs", de Jason Shaw. Publicada en https://audionautix.com/ con licencia - Creative Commons Attribution 4.0 International License.
Don’t Use Recursion In Python Any More,Python Closure — A Pythonic technique you must know: https://towardsdatascience.com/dont-use-recursion-in-python-any-more-918aad95094c.
Hilo en la lista de correo de Python Madrid: https://lists.es.python.org/pipermail/madrid/2021-January/004838.html.
Closure: https://es.wikipedia.org/wiki/Clausura_(inform%C3%A1tica).
Twisted daña el cerebro: https://twistedmatrix.com/trac/.
Black: https://pypi.org/project/black/.
from __future__ import braces
.
'
o "
.
Cuando tienes if ... else ...
, ¿Qué caso pones primero?,
¿el corto o el largo? ¿Primero la condición normal?
Microoptimizaciones que complican la legibilidad sin ganancia de rendimiento que importe en realidad.
Dispositivo de Duff: https://es.wikipedia.org/wiki/Dispositivo_de_Duff.
El "bytecode" https://es.wikipedia.org/wiki/Bytecode que genera Python no está nada optimizado. Es mejorable.
a + a
:
>>> dis.dis(lambda a: a + a)
1 0 LOAD_FAST 0 (a)
2 LOAD_FAST 0 (a)
4 BINARY_ADD
6 RETURN_VALUE
¡Guardas!
Sí se hacen algunas optimizaciones simples:
>>> dis.dis(lambda : 5 + 3)
1 0 LOAD_CONST 1 (8)
2 RETURN_VALUE
Máquina virtual de registros en vez de máquina virtual orientada a pila.
Muchas operaciones redundantes:
>>> import dis
>>> def suma(valores):
... s=0
... for i in valores:
... s+=i
... return s
...
>>> dis.dis(suma)
2 0 LOAD_CONST 1 (0)
2 STORE_FAST 1 (s)
3 4 LOAD_FAST 0 (valores)
6 GET_ITER
>> 8 FOR_ITER 12 (to 22)
10 STORE_FAST 2 (i)
4 12 LOAD_FAST 1 (s)
14 LOAD_FAST 2 (i)
16 INPLACE_ADD
18 STORE_FAST 1 (s)
20 JUMP_ABSOLUTE 8
5 >> 22 LOAD_FAST 1 (s)
24 RETURN_VALUE
¿Qué ocurre a la hora de depurar o para gestionar excepciones?
¡Guardas!
NOTA DESDE EL FUTURO:
Python 3.9.5: https://docs.python.org/release/3.9.5/whatsnew/changelog.html.
Traceback objects allow accessing frame objects without triggering audit hooks: https://bugs.python.org/issue42800.
La complejidad debe estar en tu programa, no en el lenguaje o el intérprete.
Compiladores optimizadores. Python se está quedando atrás.
Hacer caché al buscar atributos:
Issue1616125: Cached globals+builtins lookup optimization: https://bugs.python.org/issue1616125.
issue43452: Microoptimize PyType_Lookup for cache hits https://bugs.python.org/issue43452.
Detectar cambios en un diccionario, incluyendo
diccionarios internos como locals
o __builtins__
:
PEP 509 Add a private version to dict:
https://www.python.org/dev/peps/pep-0509/.
from __future__ import braces
.
import antigravity
.
import this
.
import __hello__
.
pass
o ...
(ellipsis).
Es algo interno para el API de C. No está accesible desde Python.
Cambios pequeños pueden abrir posibilidades interesantes. ¡Guardas!.
traceback.clear_frames(tb)
:
https://docs.python.org/3/library/traceback.html#traceback.clear_frames.
Manipular frame.back
.
Que una función sepa si se le está llamando de una forma síncrona o asíncrona.
Una biblioteca debe decidir si es síncrona o asíncrona y "contamina" todo tu código.
Hacer corrutinas "de verdad": https://es.wikipedia.org/wiki/Corrutina.
Persistencia y programación asíncrona.
Concepto de "awaitable": https://docs.python.org/3/library/asyncio-task.html#awaitables.
future.result()
:
https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future.result.
Vuelve a tratarse el tema de si la biblioteca estándar debe crecer o adelgazar.
Según Jesús Cea, asyncio https://docs.python.org/3/library/asyncio.html es la peor opción.
Alternativas a asyncio:
Trio: https://trio.readthedocs.io/en/stable/. Monkey patching: https://en.wikipedia.org/wiki/Monkey_patch.
La dificultad de luchar con una biblioteca que está incluída en la biblioteca estándar.
concurrent.futures
https://docs.python.org/3/library/concurrent.futures.html que
threading
https://docs.python.org/3/library/threading.html
directamente.
Transportar excepciones entre hilos.
Control de carga y paralelismo.
Queda por ultimar el detalle de cómo solucionar el problema exactamente y enviar el parche para que se integre oficialmente en Python.
Jesús Cea describe las dos opciones que está barajando:
weakrefs https://docs.python.org/3/library/weakref.html o
try ... finally
.