2 ==========================
3 Recolección de Basura en D
4 ==========================
6 :Autor: Leandro Lucarella
12 ==============================================================================
15 --------------------------------------------------
19 * Recolección de basura
20 * Lenguaje de programación D
21 * Utilidad → Software Libre → Contribución
31 --------------------------------------------------
37 * Administración automática de memoria
41 * Simplificar interfaces
42 * Mejorar eficiencia (**!**)
43 * Evitar errores de memoria
57 * Conteo de referencias
58 * Copia de semi-espacio
59 * **Marcado y barrido**
63 \multiinclude[format=pdf,graphics={height=4.5cm}]{img/mark-sweep}
65 .. dummy: para que ande bien el raw de arriba
73 * Medio siglo de investigación y desarrollo (3000+ publicaciones)
76 * ↓ Tiempo total de ejecución
77 * ↓ Cantidad de recolecciones
78 * ↓ Tiempo de recolección
79 * ↓ **Tiempo (máximo) de pausa**
85 * Organización de memoria
93 Empieza con John McCarthy en 1959
96 El Lenguaje de Programación D
97 --------------------------------------------------
99 Características Generales
100 ~~~~~~~~~~~~~~~~~~~~~~~~~
101 * Sintaxis tipo C/C++
103 * Sistema de tipos estático
112 * Programación de bajo nivel (*system-programming*) ← C/C++
119 → Conservativo + Manipulación de *root set*
121 * Programación de alto nivel ← Python/Ruby/Perl
126 → Punteros interiores
128 * Orientación a objetos ← Java
140 Recolector de Basura de D
141 ==============================================================================
143 Implementación Actual
144 --------------------------------------------------
146 Organización del Heap
147 ~~~~~~~~~~~~~~~~~~~~~
148 *Heap* → *Pools* → Páginas → Bloques + Listas de libres
150 .. image:: img/heap.pdf
159 * Tamaño fijo (por página)
163 * Más de 4096 (una página)
166 * Múltiplo de páginas: 4096, 8192, ...
167 * En páginas contiguas (y mismo *pool*)
169 * Indicadores (*bit sets* en *pool*)
194 * Con una pizca de *precisión* (``NO_SCAN``)
198 * Durante el marcado, en teoría
202 * Muy propenso a extender el tiempo de *stop-the-world* en la práctica
209 Lo Bueno, lo Malo y lo Feo
210 --------------------------------------------------
215 * Organización del *heap* (*two-level allocation*)
216 * Marcado iterativo (!\ *overflow*)
217 * *Bit set* para indicadores (caché)
229 * ↓ Configurabilidad (*no silver bullet*)
230 * ↓ Precisión (información de tipos) → Memoria inmortal
231 * ↓ Concurrencia → Grandes pausas
232 * ↓ Control sobre el factor de ocupación del *heap* → casos patológicos
236 * El código (complejo, intrincado, duplicado, poco documentado) → Difícil de
237 mantener, modificar y mejorar
245 Modificaciones Propuestas
246 ==============================================================================
249 --------------------------------------------------
253 * Hijo *nace* con una *fotografía* de la memoria del padre
254 * Aisla modificaciones en la memoria de padre e hijo
255 * Minimiza copia efectiva de memoria (*COW*)
256 * Comienza con un solo hilo (el que llamó a ``fork(2)``)
265 * Basado en el trabajo de Gustavo Rodriguez-Rivera y Vince Russo (*Non-intrusive
266 Cloning Garbage Collector with Stock Operating System Support*)
267 * Minimiza tiempo de pausa realizando fase de marcado **concurrente** vía
269 * Proceso padre sigue corriendo el programa
270 * Proceso hijo realiza fase de marcado
271 * Se comunican resultados vía memoria compartida
272 * Sincronización mínima (``fork(2)`` + ``waitpid(2)``)
280 * Hilo que disparó la recolección bloqueado hasta fin de recolección completa
281 (marcado concurrente inclusive)
282 * Otros hilos potencialmente bloqueados durante toda la recolección también
285 → Tiempo de pausa en la práctica ~= tiempo total de recolección
293 * Crea un nuevo *pool* de memoria antes de lanzar el marcado concurrente
294 * Devuelve memoria del nuevo *pool* al programa mientras termina el marcado
296 * Permite al programa (**todos** sus hilos) seguir trabajando mientras se
297 realiza el marcado concurrente
302 ↓ Tiempo de pausa real
310 * Dispara una recolección *preventiva* antes de que se agote la memoria
311 * Permite al programa (**todos** sus hilos) seguir trabajando mientras la
312 recolección *preventiva* está en progreso
313 * Si se agota la memoria antes de que la recolección *preventiva* finalice, se
315 * Combinable con *eager allocation* para evitar bloquear
316 * Pueden realizarse más recolecciones de las necesarias
319 ↑ Consumo de procesador (potencialmente)
321 ↓ Tiempo de pausa real (no garantizado)
327 Si hago una recolección cuando queda 20% de memoria libre y nadie pide más
328 memoria mientras se recolecta, es como si tuviera 20% menos de memoria
329 disponible para el programa => más recolecciones => más consumo de CPU (y
330 potencialmente run-time)
334 --------------------------------------------------
338 Adaptación del trabajo de Vincent Lang y David Simcha:
340 * Compilador genera información sobre ubicación de los punteros para cada tipo
343 * Indica si una *palabra* debe ser escaneada
344 * Indica si una palabra es un puntero
346 * Se pasa esa información al recolector al momento de pedir memoria
347 * Recolector original utiliza esa información
349 * Almacena un puntero a la información al final del bloque
350 * Utiliza la información para escanear solo palabras que son punteros (con
351 seguridad o potencialmente)
357 Optimizaciones y Otras Mejoras Menores
358 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
359 * Mejora del factor de ocupación del *heap*
360 * Caché de consultas críticas para acelerar cuellos de botella
361 * Reestructuración, modularización, simplificación y limpieza del código
362 * Pre-asignación de memoria
363 * Optimizaciones algorítmicas sobre búsquedas frecuentes
364 * Registro de pedidos de memoria y recolecciones realizadas
372 * Configurable en *tiempo de arranque*
373 * Vía variable de entorno (``D_GC_OPTS=fork=0 ./prog``)
374 * Viejas opciones convertidas
383 * ``malloc_stats_file``
384 * ``collect_stats_file``
397 ==============================================================================
400 --------------------------------------------------
404 * Múltiples corridas (20-50)
406 * Minimizar error en la medición
407 * Resultados expresados en función de:
414 * Minimizar variación entre corridas
426 * Ejercitar aspectos puntuales
427 * No realizan una tarea útil
430 * Programas pequeños - *Olden Benchmark* (5)
432 * Relativamente pequeños (400-1000 *SLOC*)
433 * Realizan una tarea útil
434 * Manipulan mucho listas y árboles asignando mucha memoria
435 * No son ideales para probar un *GC*
437 * Programas reales - **Dil** (1)
439 * Compilador de D escrito en D
440 * Grande y complejo (32K+ *SLOC*, 86 módulos, 300+ *clases*)
441 * Programado sin (limitaciones ni ventajas del) *GC* en mente
442 * Manipulación de *strings*, arreglos dinámicos y asociativos
446 * Tiempo total de ejecución
447 * Tiempo máximo de *stop-the-world*
448 * Tiempo máximo de pausa real
449 * Cantidad máxima de memoria utilizada
453 --------------------------------------------------
455 Tiempo Máximo de Stop-The-World
456 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
457 .. image:: img/norm-hist-stw.pdf
464 Explicar brevemente división de pruebas (cual es trivial, pequeña, real)
466 Tiempo Máximo de Pausa Real
467 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
468 .. image:: img/norm-hist-pause.pdf
475 Explicar que donde hay grandes diferencias, es por tiempo de barrido
477 Cantidad Máxima de Memoria Utilizada
478 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
479 .. image:: img/norm-hist-mem.pdf
486 Enganchar lo anterior con la relación con el consumo de memoria
488 Tiempo Total de Ejecución
489 ~~~~~~~~~~~~~~~~~~~~~~~~~
490 .. image:: img/norm-hist-time.pdf
497 * mcore y split bajan mucho por caché de tamaño
498 * rnddata baja mucho por marcado preciso
499 * bigarr y sbtree suben porque no hacen más que alocar
504 ==============================================================================
507 --------------------------------------------------
513 Minimizar tiempo de pausa para programas reales
515 Tiempo de pausa de Dil:
517 * *Stop-the-world* **160 veces menor** (1.66s → 0.01s)
518 * Pausa real **40 veces menor** (1.7s → 0.045s)
520 * Objetivo secundario
522 No empeorar mucho el recolector actual en ningún aspecto
524 Utilización de memoria de Dil:
526 **50% mayor** (mucho *overhead* por marcado preciso)
530 Tiempo total de ejecución de Dil:
532 Casi **3 veces menor** (55s → 20s)
538 Problemas, Limitaciones y Puntos Pendientes
539 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540 * Explosión de uso de memoria con *eager allocation*
541 * Eficiencia del marcado preciso
542 * Mejorar predicción de *early collection*
543 * Experimentar con ``clone(2)``
549 Trabajos Relacionados
550 ~~~~~~~~~~~~~~~~~~~~~
551 * *Memory Management in the D Programming Language*
553 Vladimir Panteleev. Proyecto de licenciatura, Universitatea Tehnică
556 * *Integrate Precise Heap Scanning Into the GC*
558 David Simcha (GC + diseño) y Vincent Lang (compilador). No formal, *bug
561 * *Non-intrusive Cloning Garbage Collection with Stock Operating System Support*
563 Gustavo Rodriguez-Rivera y Vince Russo. Software Practiceand Experience
564 Volumen 27, Número 8. Agosto 1997.
572 * Organización de memoria
575 * Concurrencia → *Lock* **global**
591 .. vim: set et sw=4 sts=4 spell spelllang=es :