Una recolección de basura no solo se deshace de los objetos no referenciados, sino que también compacta el montón. Esa es una optimización muy importante. No solo hace que el uso de la memoria sea más eficiente (sin agujeros sin usar), sino que hace que la memoria caché de la CPU sea mucho más eficiente. El caché es un gran problema en los procesadores modernos, son un orden de magnitud más rápido que el bus de memoria.
La compactación se realiza simplemente copiando bytes. Sin embargo, eso lleva tiempo. Cuanto más grande sea el objeto, es más probable que el costo de copiarlo supere las posibles mejoras en el uso de la memoria caché de la CPU.
Así que ejecutaron varios puntos de referencia para determinar el punto de equilibrio. Y llegó a 85.000 bytes como punto de corte donde la copia ya no mejora el rendimiento. Con una excepción especial para las matrices de double, se consideran "grandes" cuando la matriz tiene más de 1000 elementos. Esa es otra optimización para el código de 32 bits, el asignador de montón de objetos grandes tiene la propiedad especial de que asigna memoria en direcciones que están alineadas con 8, a diferencia del asignador generacional regular que solo asigna alineado con 4. Esa alineación es un gran problema para el doble , leer o escribir un doble mal alineado es muy caro. Curiosamente, la escasa información de Microsoft nunca menciona arreglos largos, no estoy seguro de qué pasa con eso.
Fwiw, hay mucha angustia entre los programadores porque el montón de objetos grandes no se compacta. Esto invariablemente se activa cuando escriben programas que consumen más de la mitad de todo el espacio de direcciones disponible. Seguido mediante el uso de una herramienta como un generador de perfiles de memoria para averiguar por qué el programa falló a pesar de que todavía había mucha memoria virtual sin usar disponible. Dicha herramienta muestra los agujeros en el LOH, trozos de memoria no utilizados donde anteriormente vivía un objeto grande pero se recolectaba la basura. Tal es el precio inevitable del LOH, el agujero solo puede ser reutilizado por una asignación para un objeto que sea de tamaño igual o menor. El verdadero problema es asumir que un programa debería poder consumir toda la memoria virtual en cualquier momento.
Un problema que, de lo contrario, desaparece por completo con solo ejecutar el código en un sistema operativo de 64 bits. Un proceso de 64 bits tiene 8 terabytes de espacio de direcciones de memoria virtual disponible, 3 órdenes de magnitud más que un proceso de 32 bits. No puedes quedarte sin agujeros.
En pocas palabras, LOH hace que el código se ejecute de manera más eficiente. A costa de utilizar un espacio de direcciones de memoria virtual disponible menos eficiente.
ACTUALIZACIÓN, .NET 4.5.1 ahora admite la compactación de la propiedad LOH, GCSettings.LargeObjectHeapCompactionMode . Cuidado con las consecuencias por favor.