El módulo “tracemalloc”

1 El módulo “tracemalloc”Jesús Cea Avión @jcea httpS://w...
Author: 西炭 韩
0 downloads 13 Views

1 El módulo “tracemalloc”Jesús Cea Avión @jcea httpS://www.jcea.es/ httpS://blog.jcea.es/ PyConES Noviembre 2015

2 Jesús Cea Avión Programando Python desde 1996 (Python 1.4).Core Developer desde 2008 (Python 2.6 y 3.0). Fundador de Python Madrid y Python España, instrumental para la creación de Python Vigo. Miembro de las dos Juntas Directivas. Listas de correo, repositorio Mercurial, calendario de eventos, Twitter, OpenBadges. Consultor y Freelance a tu disposición. PyConES Noviembre 2015

3 tracemalloc Contabiliza el consumo en cada línea de código.Podemos comparar el uso de memoria en dos momentos diferentes. Permite identificar el “traceback” del punto en el que se ha creado un objeto concreto. Información capturada ajustable. Cero sobrecarga cuando no se usa. Buen complemento para el módulo estándar GC. PyConES Noviembre 2015

4 tracemalloc La información se puede volcar a disco para analizarla en diferido o con otras herramientas. Utiliza los hooks del PEP 0445, muy interesante. Comparado con otros sistemas de profiling de memoria: Incluído en la librería estándar. Permite identificar dónde se ha creado un objeto concreto. No clasifica la memoria por tipo de objeto. PyConES Noviembre 2015

5 tracemalloc Módulo en la librería estándar desde Python 3.4.0.Disponible para Python 2.7 y 3.3. Requiere una versión parcheada del intérprete. Hace falta recompilarlo. https://pypi.python.org/pypi/pytracemalloc/ PyConES Noviembre 2015

6 Ejemplo: régimen estacionario (1)import tracemalloc, threading, time, gc def print_malloc() : while True : time.sleep(60) gc.collect() # Probar a no hacerlo snapshot = tracemalloc.take_snapshot() top_stats = snapshot.statistics('lineno') print("OVERHEAD:", tracemalloc.get_tracemalloc_memory()) print("MEMORIA:", tracemalloc.get_traced_memory()) for stat in top_stats[:10] : print(stat) tracemalloc.start() t = threading.Thread(target=print_malloc) t.setDaemon(True) t.start() PyConES Noviembre 2015

7 Ejemplo: régimen estacionario (2)Ejecutando como “python3”: OVERHEAD: MEMORIA: ( , ) :222: size=622 KiB, count=1747, average=365 B :473: size=478 KiB, count=5054, average=97 B [...] Ejecutando “PYTHONTRACEMALLOC=1 python3” OVERHEAD: MEMORIA: ( , ) :473: size=1446 KiB, count=16515, average=90 B :222: size=806 KiB, count=2927, average=282 B PyConES Noviembre 2015

8 Ejemplo: Volcado para análisis posteriorimport tracemalloc, threading, time, gc def print_malloc() : for i in range( ) : time.sleep(60) gc.collect() snapshot = tracemalloc.take_snapshot() snapshot.dump("z-tracemalloc.%010d.snapshot" %i) tracemalloc.start() t = threading.Thread(target=print_malloc) t.setDaemon(True) t.start() PyConES Noviembre 2015

9 Ejemplo: Leak de memoria>>> import tracemalloc >>> a=tracemalloc.Snapshot.load(" snapshot") >>> b=tracemalloc.Snapshot.load(" snapshot") >>> for stat in b.compare_to(a, "lineno")[:2] : ... print(stat) ... ./z.py:10: size=50.7 KiB (+3985 B), count=39 (+3), average=1330 B :222: size=622 KiB (+0 B), count=1747 (+0), average=365 B >>> len(b.compare_to(a, "lineno")) 943 >>> os.stat(" snapshot").st_size 85100 El snapshot incluye información de toda la memoria gestionada, aunque no haya cambios. PyConES Noviembre 2015

10 Ejemplo: Identificar dónde se creó un objeto (1)import tracemalloc tracemalloc.start() a="123" print(tracemalloc.get_object_traceback(a)) a="123"*7 El resultado es: None ./prueba.py:7 El primer caso no reserva memoria, el valor del objeto está directamente en el código compilado. PyConES Noviembre 2015

11 Ejemplo: Identificar dónde se creó un objeto (2)>>> dis.dis(...) LOAD_CONST ('123') 3 STORE_FAST (a) [...] LOAD_CONST ('123') 28 LOAD_CONST (7) 31 BINARY_MULTIPLY 32 STORE_FAST (a) El primer caso no requiere reservar memoria. El segundo caso construye el valor del objeto en tiempo de ejecución. PyConES Noviembre 2015

12 Sugerencias: Volcar los “snapshots” a disco para análisis cómodo.Tener un hilo para acceso y exploración interactiva. https://docs.python.org/3.5/library/cmd.html Dependiendo de la aplicación, es preferible empezar agrupando por “filename” o por “lineno”. Tracemalloc se puede activar y desactivar en cualquier momento, podemos analizar secciones del programa de forma selectiva. PyConES Noviembre 2015

13 Usos prácticos: Memory leaks. Reducir el consumo de memoria:Caso práctico: Reducir el consumo de memoria al 1.6% cambiando una secuencia [True, False, True...] por una matriz de bits: https://pypi.python.org/pypi/bitarray/ PyConES Noviembre 2015

14 ¿Rendimiento? No es para usar en producción en todo tu código:#!/usr/bin/env python3 import timeit import tracemalloc, gc gc.disable() print(timeit.timeit("[i for i in range(10000, 20000)]", number=1000)) tracemalloc.start() tracemalloc.stop() Resultado: PyConES Noviembre 2015

15 ¿Rendimiento? El consumo de memoria depende del número de “frames” que capturamos. tracemalloc.clear_traces() Puede no ser utilizable en entornos limitados (RaspPi) con programas complejos. PyConES Noviembre 2015

16 ¿Preguntas? Visibilidad de la memoria de módulos en C.Combinación de los módulos tracemalloc y gc. Pros y contras entre identificar bloques de memoria e identificar tipos de objetos. Depende de si el programa crea muchos objetos de tipo distinto o no. En Python es típico usar tipos básicos. PyConES Noviembre 2015

17 Referencias adicionalesDocumentación: https://pytracemalloc.readthedocs.org/ https://docs.python.org/3.5/library/tracemalloc.html https://www.python.org/dev/peps/pep-0454/ https://docs.python.org/3.5/library/gc.html https://www.python.org/dev/peps/pep-0445/ https://docs.python.org/3.5/library/cmd.html Otras opciones de “profiling” de memoria: https://stackoverflow.com/questions/110259/ PyConES Noviembre 2015

18 ¡Gracias! Jesús Cea Avión [email protected] @jcea httpS://www.jcea.es/httpS://blog.jcea.es/ PyConES Noviembre 2015