Wyrzucanie elementów bezużytecznych nie tylko usuwa obiekty, do których nie istnieją odniesienia, ale także kompaktuje stertę. To bardzo ważna optymalizacja. Nie tylko zwiększa to wykorzystanie pamięci (brak nieużywanych dziur), ale także znacznie zwiększa wydajność pamięci podręcznej procesora. Pamięć podręczna to naprawdę poważna sprawa w przypadku nowoczesnych procesorów, są one o rząd wielkości szybsze niż szyna pamięci.
Kompaktowanie odbywa się po prostu przez kopiowanie bajtów. To jednak wymaga czasu. Im większy obiekt, tym większe prawdopodobieństwo, że koszt jego skopiowania przeważa nad możliwą poprawą wykorzystania pamięci podręcznej procesora.
Przeprowadzili więc szereg testów porównawczych, aby określić próg rentowności. I osiągnął 85 000 bajtów jako punkt odcięcia, w którym kopiowanie nie poprawia już wydajności. Ze specjalnym wyjątkiem dla tablic double, są one uważane za „duże”, gdy tablica ma więcej niż 1000 elementów. To kolejna optymalizacja dla 32-bitowego kodu, alokator dużych stert obiektów ma specjalną właściwość polegającą na tym, że przydziela pamięć pod adresy, które są wyrównane do 8, w przeciwieństwie do zwykłego alokatora pokoleń, który przydziela tylko wyrównane do 4. Takie wyrównanie jest wielką sprawą dla podwójnych , czytanie lub pisanie źle wyrównanego podwójnego jest bardzo kosztowne. Co dziwne, rzadkie informacje firmy Microsoft nigdy nie wspominają o tablicach długich, nie jestem pewien, o co chodzi.
Fwiw, jest wiele obaw programistów co do tego, że sterta dużych obiektów nie jest kompaktowana. To niezmiennie jest wyzwalane, gdy piszą programy, które zajmują ponad połowę całej dostępnej przestrzeni adresowej. Następnie za pomocą narzędzia takiego jak profiler pamięci, aby dowiedzieć się, dlaczego program zbombardował, mimo że wciąż było dostępnych dużo nieużywanej pamięci wirtualnej. Takie narzędzie pokazuje dziury w LOH, nieużywane fragmenty pamięci, w których wcześniej mieszkał duży obiekt, ale zbierano śmieci. Taka jest nieunikniona cena LOH, dziura może być ponownie wykorzystana tylko przez alokację dla obiektu o równym lub mniejszym rozmiarze. Prawdziwy problem polega na założeniu, że program powinien mieć możliwość wykorzystania całej pamięci wirtualnej w dowolnym momencie.
Problem, który w przeciwnym razie znika całkowicie po uruchomieniu kodu w 64-bitowym systemie operacyjnym. Proces 64-bitowy ma 8 terabajtów dostępnej przestrzeni adresowej pamięci wirtualnej, o 3 rzędy wielkości więcej niż proces 32-bitowy. Po prostu nie możesz zabraknąć dziur.
Krótko mówiąc, LOH sprawia, że kod działa wydajniej. Kosztem mniej wydajnego wykorzystania dostępnej przestrzeni adresowej pamięci wirtualnej.
UPDATE, .NET 4.5.1 obsługuje teraz kompaktowanie właściwości LOH, GCSettings.LargeObjectHeapCompactionMode . Uważaj na konsekwencje, proszę.