Różnica między „na stercie” i „poza stertą”


Odpowiedzi:


169

Magazyn na stercie odnosi się do obiektów, które będą obecne w stercie Java (a także będą podlegać GC). Z drugiej strony magazyn poza stertą odwołuje się do (serializowanych) obiektów, które są zarządzane przez EHCache, ale są przechowywane poza stertą (i również nie podlegają GC). Ponieważ magazyn poza stertą jest nadal zarządzany w pamięci, jest on nieco wolniejszy niż magazyn na stercie, ale nadal szybszy niż magazyn na dysku.

Wewnętrzne szczegóły związane z zarządzaniem i korzystaniem ze sklepu poza stertą nie są zbyt widoczne w linku zamieszczonym w pytaniu, więc rozsądnie byłoby zapoznać się ze szczegółami Terracotta BigMemory , która służy do zarządzania poza dyskiem sklep. BigMemory (magazyn poza stertą) ma być używany w celu uniknięcia narzutu GC na stercie, który ma kilka megabajtów lub gigabajtów. BigMemory wykorzystuje przestrzeń adresową pamięci procesu JVM za pośrednictwem bezpośrednich ByteBufferów , które nie podlegają GC w przeciwieństwie do innych natywnych obiektów Java.


18
+1 za wzmiankę o bezpośrednich ByteBuffers do dalszej eksploracji;)
Max

3
Direct ByteBuffers oferują dostęp do niezarządzanej pamięci, ale same podlegają GC (w przeciwieństwie do danych, na które wskazują). Jest to ważne, ponieważ bezpośredni ByteBuffer (rodzaj ByteBuffer.allocateDirect, a nie rodzaj MMap) zostanie zebrany przez GC, a kiedy zostanie zebrany, zostanie wyzwolony Deallocater, skutecznie zbierając również niezarządzaną pamięć.
Nitsan Wakart

Używanie Unsafe do przydzielania obiektów wygląda na znacznie lepszą wydajność odczytu i zapisu w porównaniu z Onheap / DirectByteBuffers / ByteBuffers. ashkrit.blogspot.com/2013/07/…
Joe C

98

z http://code.google.com/p/fast-serialization/wiki/QuickStartHeapOff

Co to jest rozładowywanie sterty?

Zwykle wszystkie alokowane obiekty nietrwałe są zarządzane przez moduł odśmiecania pamięci Java. Chociaż maszyna wirtualna wykonuje porządną robotę przy usuwaniu elementów bezużytecznych, w pewnym momencie musi wykonać tak zwane „pełne GC”. Pełny GC obejmuje skanowanie całego przydzielonego sterty, co oznacza, że ​​przerwy / spowolnienia GC są proporcjonalne do rozmiaru sterty aplikacji. Nie ufaj więc nikomu, kto powie Ci, że „Pamięć jest tania”. W javie zużycie pamięci obniża wydajność. Dodatkowo możesz uzyskać znaczące przerwy, używając rozmiarów sterty> 1 GB. Może to być nieprzyjemne, jeśli masz jakieś rzeczy w czasie zbliżonym do rzeczywistego, w klastrze lub sieci proces Java może przestać odpowiadać i zostać usunięty z klastra.

Jednak dzisiejsze aplikacje serwerowe (często budowane w oparciu o rozbudowane frameworki ;-)) z łatwością wymagają dużo więcej niż 4Gb.

Jednym z rozwiązań tych wymagań dotyczących pamięci jest „odciążenie” części obiektów do stosu innego niż Java (przydzielanego bezpośrednio z systemu operacyjnego). Na szczęście java.nio udostępnia klasy do bezpośredniego przydzielania / odczytywania i zapisywania „niezarządzanych” fragmentów pamięci (nawet plików mapowanych w pamięci).

Można więc przydzielić duże ilości „niezarządzanej” pamięci i użyć jej do zapisywania tam obiektów. Aby zapisać dowolne obiekty w niezarządzanej pamięci, najbardziej realnym rozwiązaniem jest użycie serializacji. Oznacza to, że aplikacja serializuje obiekty do pamięci offheap, a później obiekt można odczytać za pomocą deserializacji.

Rozmiar sterty zarządzany przez maszynę wirtualną java może być mały, więc przerwy w GC są w milisach, wszyscy są zadowoleni, praca wykonana.

Jest oczywiste, że wydajność takiego bufora poza stertą zależy głównie od wydajności implementacji serializacji. Dobra wiadomość: z jakiegoś powodu serializacja FST jest dość szybka :-).

Przykładowe scenariusze użycia:

  • Pamięć podręczna sesji w aplikacji serwera. Użyj pliku mapowanego w pamięci do przechowywania gigabajtów (nieaktywnych) sesji użytkowników. Gdy użytkownik zaloguje się do aplikacji, możesz szybko uzyskać dostęp do danych dotyczących użytkownika bez konieczności korzystania z bazy danych.
  • Buforowanie wyników obliczeń (kwerendy, strony html,…) (dotyczy tylko sytuacji, gdy obliczenia są wolniejsze niż deserializacja obiektu wynikowego ofc).
  • bardzo prosta i szybka trwałość przy użyciu plików mapowanych w pamięci

Edycja: W przypadku niektórych scenariuszy można wybrać bardziej wyrafinowane algorytmy zbierania śmieci, takie jak ConcurrentMarkAndSweep lub G1, aby obsługiwać większe sterty (ale ma to również ograniczenia przekraczające sterty 16 GB). Dostępna jest również komercyjna maszyna JVM z ulepszonym „bez wstrzymywania” GC (Azul).


4
„alokuj duże ilości 'niezarządzanej' pamięci i używaj jej do zapisywania w niej obiektów” - nie możesz składować obiektów z taniej. Możesz przechowywać prymitywy, możesz je opakować w dowolną bibliotekę, ale to nie są Obiekty. Dane, które umieszczasz w magazynie, nie mają nagłówka obiektu, nie możesz ich synchronizować, nie możesz odwoływać się do nich za pomocą pola odniesienia w innym obiekcie.
Nitsan Wakart

41

Sterta to miejsce w pamięci, w którym żyją dynamicznie przydzielane obiekty. Jeśli użyłeś, newto jest na stercie. To w przeciwieństwie do miejsca na stosie, w którym znajduje się stos funkcji. Jeśli masz zmienną lokalną, to odniesienie to znajduje się na stosie. Sterta Javy podlega wyrzucaniu elementów bezużytecznych, a obiektów można używać bezpośrednio.

Magazyn poza stertą EHCache usuwa zwykły obiekt ze sterty, serializuje go i przechowuje jako bajty w porcji pamięci, którą zarządza EHCache. To jak przechowywanie go na dysku, ale nadal jest w pamięci RAM. W tym stanie obiekty nie nadają się do bezpośredniego użytku, należy je najpierw zdeserializować. Nie podlega również wyrzucaniu elementów bezużytecznych.


Czy to nie jest po prostu nadal w stercie, ale w postaci seryjnej?
Pacerier,

1
jak to czyni go bardziej wydajnym?
Pacerier,

2
Jest wiele sposobów. Ponieważ obiekty nie znajdują się już na głównej stercie Javy, nie marnują czasu garbage collectora, nie fragmentują sterty maszyny JVM i zwalniają miejsce na inne częściej używane obiekty. Ponadto, ponieważ są one serializowane i prawdopodobnie nie będą potrzebne w najbliższej przyszłości, mogą być kompresowane, przenoszone w razie potrzeby, a nawet stronicowane na dysk.
Adam

1
W Hotspot czas pauzy GC zależy bezpośrednio od rozmiaru sterty. BigMemory zapewnia ten kompromis, wykorzystując pamięć RAM zamiast sterty, aby ograniczyć wstrzymanie GC do minimum i uniknąć kosztu IO dostępu do dysku.
Chander Shivdasani


1

JVM nie wie nic o pamięci poza stertą. Ehcache implementuje pamięć podręczną na dysku oraz pamięć podręczną w pamięci.


1

Nie 100%; wydaje się jednak, że sterta jest obiektem lub zestawem przydzielonej przestrzeni (w pamięci RAM), która jest wbudowana w funkcjonalność kodu albo samą Javę, albo, co bardziej prawdopodobne, funkcjonalność z samego ehcache, a pamięć RAM poza stertą ma własny system, jak dobrze; jednak wygląda na to, że jest o jedną wielkość wolniejszy, ponieważ nie jest tak zorganizowany, co oznacza, że ​​może nie używać sterty (co oznacza jeden długi zestaw miejsca w pamięci RAM), a zamiast tego używa różnych przestrzeni adresowych, co prawdopodobnie czyni go nieco mniej wydajnym.

Oczywiście następnym niższym poziomem jest samo miejsce na dysku twardym.

Nie używam ehcache, więc możesz nie chcieć mi ufać, ale to właśnie zebrałem z ich dokumentacji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.