Una garbage collection non si limita a eliminare gli oggetti non referenziati, ma compatta anche l'heap. Questa è un'ottimizzazione molto importante. Non solo rende più efficiente l'utilizzo della memoria (senza buchi inutilizzati), ma rende la cache della CPU molto più efficiente. La cache è davvero un grosso problema sui processori moderni, sono un semplice ordine di grandezza più veloci del bus di memoria.
La compattazione viene eseguita semplicemente copiando i byte. Ciò tuttavia richiede tempo. Più grande è l'oggetto, più è probabile che il costo della copia superi i possibili miglioramenti nell'utilizzo della cache della CPU.
Quindi hanno eseguito una serie di benchmark per determinare il punto di pareggio. Ed è arrivato a 85.000 byte come punto limite in cui la copia non migliora più le prestazioni. Con un'eccezione speciale per gli array di double, sono considerati "grandi" quando l'array ha più di 1000 elementi. Questa è un'altra ottimizzazione per il codice a 32 bit, l'allocatore di heap di oggetti di grandi dimensioni ha la proprietà speciale di allocare memoria agli indirizzi allineati a 8, a differenza del normale allocatore generazionale che alloca solo allineato a 4. Quell'allineamento è un grosso problema per il doppio , leggere o scrivere un doppio disallineato è molto costoso. Stranamente le scarse informazioni di Microsoft non menzionano mai array di lunga durata, non sono sicuro di cosa ci sia.
Fwiw, c'è molta angoscia del programmatore sul fatto che l'heap di oggetti di grandi dimensioni non viene compresso. Ciò viene invariabilmente attivato quando scrivono programmi che consumano più della metà dell'intero spazio di indirizzi disponibile. Seguito utilizzando uno strumento come un profiler di memoria per scoprire perché il programma è stato bombardato anche se c'era ancora molta memoria virtuale inutilizzata disponibile. Un tale strumento mostra i buchi nel LOH, blocchi di memoria inutilizzati in cui in precedenza viveva un oggetto di grandi dimensioni ma veniva raccolto dalla spazzatura. Tale è l'inevitabile prezzo del LOH, il buco può essere riutilizzato solo da un'allocazione per un oggetto di dimensioni uguali o inferiori. Il vero problema è supporre che a un programma dovrebbe essere consentito di consumare tutta la memoria virtuale in qualsiasi momento.
Un problema che altrimenti scompare completamente semplicemente eseguendo il codice su un sistema operativo a 64 bit. Un processo a 64 bit dispone di 8 terabyte di spazio degli indirizzi di memoria virtuale disponibile, 3 ordini di grandezza in più rispetto a un processo a 32 bit. Non puoi rimanere senza buchi.
Per farla breve, LOH rende il codice più efficiente. Al costo di utilizzare lo spazio degli indirizzi di memoria virtuale disponibile meno efficiente.
UPDATE, .NET 4.5.1 ora supporta la compattazione della proprietà LOH, GCSettings.LargeObjectHeapCompactionMode . Attenti alle conseguenze per favore.