Qué cuesta de verdad la recolección de basura en un programa

Fuentes: What garbage collection actually costs

La recolección de basura (GC) no cobra por la memoria usada, sino por los objetos vivos y las referencias entre ellos: por eso un grafo de muchos objetos pequeños resulta mucho más caro de barrer que un único búfer del mismo tamaño. El artículo explica que toda la memoria dinámica vive en el heap —la pila es invisible al recolector— y que cada ciclo de GC consiste en reconstruir el grafo de objetos alcanzables partiendo de las raíces, para liberar lo que queda fuera. Durante ese recorrido, cada escritura de puntero que hace el programa obliga a notificar al recolector, un trabajo adicional que se imputa al programa, no al GC, y que encarece aún más al código denso en punteros.

Frente a la gestión manual de C o a la gestionada en compilación de Rust, los runtimes con GC —Go, Java y la mayoría de lenguajes modernos— intercambian control por seguridad, aunque los distintos algoritmos (tracing completo, generacional, incremental…) solo cambian las constantes y el perfil de asignación para el que están optimizados, no los factores que determinan el coste.

El texto propone medir antes de optimizar: primero, comprobar qué porcentaje de CPU consume el recolector (Go lo expone en runtime/metrics, Java en sus logs de GC o con un profiler); después, medir la tasa de churn (creación y descarte de objetos); y por último, el tamaño del grafo vivo y su densidad de referencias. Si la cuota de CPU dedicada al GC es pequeña, no merece la pena seguir afinando.