Jak efektywnie buforować obiekty w Javie przy użyciu dostępnej pamięci RAM?

Muszę buforować obiekty w Javie, używając proporcji dostępnej pamięci RAM. Wiem, że inni zadawali to pytanie, ale żadna z odpowiedzi nie spełnia moich wymagań.

Moje wymagania to:

  • proste i lekkie
  • nie dramatycznie wolniej niż zwykły HashMap
  • Użyj LRU, lub niektórych zasad usuwania, które zbliżają się do LRU

Próbowałem LinkedHashMap, jednak wymaga podania maksymalnej liczby elementów, a ja nie wiedz ile elementów potrzeba do zapełnienia dostępnej pamięci RAM(ich rozmiary będą się znacznie różnić).

Moim obecnym podejściem jest użycie MapMaker Google Collection w następujący sposób:

Map<String, Object> cache = new MapMaker().softKeys().makeMap();

Wydawało się to atrakcyjne, ponieważ powinno automatycznie usuwać elementy, gdy potrzebuje więcej pamięci RAM, jednak istnieje poważny problem: jego zachowanie polega na wypełnieniu całej dostępnej pamięci RAM, w którym to momencie GC zaczyna tracić, a wydajność całej aplikacji dramatycznie się pogarsza.

Słyszałem o rzeczy takie jak EHCache, ale wydaje się dość ciężki do tego, czego potrzebuję, i nie jestem pewien, czy jest wystarczająco szybki dla mojej aplikacji(pamiętając, że rozwiązanie nie może być znacznie wolniejsze niż HashMap).

Author: Kevin Bourrillion, 2010-01-29

12 answers

Mam podobne wymagania do ciebie-współbieżność (na 2 procesorach hexacore) i LRU lub podobne-a także próbowałem Guava MapMaker. Znalazłem softValues () znacznie wolniejsze niż weakValues (), ale obie sprawiły, że moja aplikacja była potwornie powolna, gdy zapełniła się pamięć.

Próbowałem WeakHashMap i było to mniej problematyczne, o dziwo nawet szybsze niż używanie LinkedHashMap jako pamięci podręcznej LRU za pomocą metody removeEldestEntry ().

Ale najszybszy dla mnie jest ConcurrentLinkedHashMap który sprawił, że moja aplikacja 3-4 (!!) razy szybciej niż jakikolwiek inny cache próbowałem. Radość, po dniach frustracji! Najwyraźniej został włączony do Mapmmaker Guava, ale funkcja LRU nie jest w guava r07 w żadnym wypadku. Mam nadzieję, że ci się uda.

 7
Author: Jonathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-04 00:17:47

Zaimplementowałem bufory serwalowe i jest to prawdopodobnie równie trudne, jak implementacja nowego źródła danych lub threadpool, moim zaleceniem jest użycie jboss-cache lub innego znanego bufora lib. Więc będziesz dobrze spać bez problemów

 4
Author: stacker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 00:27:07

Słyszałem o takich rzeczach jak EHCache, ale wydaje się dość ciężki do tego, czego potrzebuję, i nie jestem pewien, czy jest wystarczająco szybki dla mojej aplikacji(pamiętając, że rozwiązanie nie może być znacznie wolniejsze niż HashMap).

Naprawdę Nie wiem, czy można powiedzieć, że EHCache jest ciężki. Przynajmniej nie uważam EHCache za taki, zwłaszcza gdy używam Pamięci (która jest wspierana przez rozszerzony LinkedHashMap i jest oczywiście najszybszy opcja buforowania). Powinieneś spróbować.

 3
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 08:13:57

Wierzę, że to będzie jedyny rozsądny sposób, by dostać to, o co prosisz. Jeśli "GC zacznie się trząść, a wydajność całej aplikacji dramatycznie się pogorszy", powinieneś poświęcić trochę czasu na odpowiednie ustawienie różnych parametrów strojenia. Ten dokument może wydawać się trochę onieśmielający na początku, ale w rzeczywistości jest napisany bardzo jasno i jest kopalnią przydatnych informacji na temat GC:

Http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf

 2
Author: Kevin Bourrillion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 19:32:29

Nie wiem, czy byłoby to proste rozwiązanie, szczególnie w porównaniu z EHCache lub podobnym, ale czy przyjrzałeś się Bibliotece Javolution? Nie jest przeznaczony do tego, ale w pakiecie javolution.context mają one wzorzec alokatora, który może ponownie używać obiektów bez konieczności usuwania śmieci. W ten sposób ograniczają tworzenie obiektów i usuwanie śmieci do minimum, co jest ważną funkcją programowania w czasie rzeczywistym. Być może powinieneś spojrzeć i spróbować dostosować go do swojego problem.

 1
Author: omerkudat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 09:35:38

To wydawało się atrakcyjne, jak powinno automatycznie usuwaj elementy, gdy to potrzebuje więcej pamięci RAM, jednak jest poważny problem: jego zachowanie polega na wypełnij wszystkie dostępne pamięci RAM

Używanie klawiszy miękkich pozwala na usuwanie obiektów z pamięci podręcznej, gdy żadne inne obiekty nie odwołują się do nich (tzn. gdy jedyną rzeczą odnoszącą się do klucza pamięci podręcznej jest sama pamięć podręczna). Nie gwarantuje to żadnego innego rodzaju wydalenia.

Większość rozwiązań, które znajdziesz będzie be funkcje dodane na górze klas map java, w tym EhCache.

Przeglądałeś commons-collections LRUMap?

Należy zauważyć, że istnieje otwarty problem przeciwko MapMaker, aby zapewnić funkcjonalność LRU/MRU. Być może Możesz również wyrazić swoją opinię w tym miejscu

 0
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 23:56:45

Używając istniejącej pamięci podręcznej, przechowuj WeakReference, a nie zwykłe odwołania do obiektów.

Jeśli w GC zaczyna brakować wolnego miejsca, wartości utrzymywane przez WeakReferences zostaną zwolnione.

 0
Author: Lachlan Roche,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 00:03:22

W przeszłości używałem JCS . Możesz skonfigurować konfigurację , aby spróbować spełnić twoje potrzeby. Nie jestem pewien, czy spełni to wszystkie twoje wymagania/potrzeby, ale stwierdziłem, że jest dość potężny, gdy go używałem.

 0
Author: ralph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 00:50:20

Nie można "usuwać elementów" można tylko zatrzymać się, aby je twardo odwołać i poczekać, aż GC je wyczyści, więc idź dalej z kolekcjami Google...

 0
Author: pgras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 07:05:32

Nie znam łatwego sposobu na ustalenie rozmiaru obiektu w Javie. Dlatego nie sądzę, że znajdziesz sposób na ograniczenie struktury danych przez ilość pamięci RAM, którą zajmuje.

Bazując na tym założeniu, utkniesz z ograniczeniem go o liczbę obiektów w pamięci podręcznej. Sugerowałbym uruchamianie symulacji kilku rzeczywistych scenariuszy użytkowania i zbieranie statystyk dotyczących typów obiektów, które trafiają do pamięci podręcznej. Następnie można obliczyć statystycznie średnią wielkość i liczbę obiektów możesz sobie pozwolić na pamięć podręczną. Nawet jeśli jest to tylko przybliżenie ilości pamięci RAM, którą chcesz poświęcić pamięci podręcznej, może to być wystarczająco dobre.

Jeśli chodzi o implementację pamięci podręcznej, w moim projekcie (aplikacji krytycznej pod względem wydajności) używamy EhCache i osobiście nie uważam go za ciężki.

W każdym razie wykonaj kilka testów z kilkoma różnymi konfiguracjami (pod względem wielkości, polityki eksmisji itp.) i dowiedzieć się, co działa najlepiej dla Ciebie.

 0
Author: Eli Acherkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 07:22:16

Buforowanie czegoś, SoftReference może najlepszy sposób, jaki do tej pory mogę sobie wyobrazić.

Albo możesz na nowo stworzyć obiekt-pulę. Że każdy przedmiot, którego nie używasz, nie musisz go niszczyć. Ale to, aby zapisać CPU, a nie zapisać pamięci

 0
Author: hqt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-23 03:55:07

Zakładając, że chcesz, aby bufor był bezpieczny dla wątków, powinieneś sprawdzić przykład bufora w książce Briana Goetza "współbieżność Javy w praktyce". Nie mogę tego polecić.

 -3
Author: Steve Emmerson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 00:21:27