2013-07-21 16 views
15

W mojej aplikacji używam słownika (wspierającego dodawanie, usuwanie, aktualizowanie i wyszukiwanie), w którym oba klucze i wartości są lub mogą być przekształcone do postaci szeregowej (wartości mogą być całkiem duże obiekty graficzne). Doszedłem do tego stopnia, że ​​słownik stał się tak duży, że przytrzymanie go całkowicie w pamięci zaczęło czasami wyzwalać OutOfMemoryException (czasami w metodach słownikowych, a czasem w innych częściach kodu).Słownik, który może zapisywać jego elementy rzadziej odwiedzane na dysku

Po próbie całkowitej zamiany słownika na bazę danych wydajność spadła do niedopuszczalnego poziomu.

Analiza wzorców użycia słownika wykazała, że ​​zazwyczaj mniejsza część wartości jest "gorąca" (są dostępne dość często), a reszta (większa część) jest "zimna" (dostęp rzadko lub nigdy). Trudno powiedzieć, kiedy zostanie dodana nowa wartość, jeśli będzie ona gorąca lub zimna, ponadto niektóre wartości mogą migrować w tę iz powrotem pomiędzy gorącymi i zimnymi częściami w czasie.

Wydaje mi się, że potrzebuję implementacji słownika, który będzie w stanie przepłukać swoje zimne wartości na dysk w przypadku niskiej pamięci, a następnie ponownie załadować niektóre z nich na żądanie i przechowywać je w pamięci do następnego zdarzenia o niskiej pamięci występuje wtedy, gdy ich stan gorący/zimny zostanie ponownie oceniony. Najlepiej byłoby, gdyby implementacja precyzyjnie dostosowywała rozmiary jej gorących i zimnych części oraz czasu płukania w zależności od profilu użycia pamięci w aplikacji, aby zmaksymalizować ogólną wydajność. Ponieważ istnieje kilka wystąpień słownika w aplikacji (z różnymi typami klucz/wartość), myślę, że mogą potrzebować skoordynować swoje przepływy pracy.

Czy możesz zasugerować, jak zaimplementować taki słownik?

+5

Czy myślisz o dodaniu pamięci podręcznej do podejścia db? Myślę, że standardowa pamięć podręczna z wygaszaniem może poprawić wydajność. – empi

Odpowiedz

0

tylko pomysł - nigdy nie zrobił i nigdy nie używane System.Runtime.Caching:

Wdrożenie owijkę wokół MemoryCache które:

  1. dodać elementy z zwrotnego eksmisji określony. Oddzwanianie umieszcza eksmitowane przedmioty w bazie danych.
  2. Pobierz element z bazy danych i wróć do MemoryCache, jeśli element jest nieobecny w MemoryCache podczas pobierania.
  3. Jeśli spodziewasz się dużej liczby żądań dotyczących brakujących elementów, zarówno w bazie danych, jak i w pamięci, prawdopodobnie będziesz musiał zaimplementować filtr kwitowania lub klucze pamięci podręcznej również dla obecnych/brakujących elementów.
0

Mam podobny problem w przeszłości.

Koncepcja, której szukasz, jest odczytaną pamięcią podręczną z kolejką LRU (ostatnio używane lub ostatnio używane).

Is it there any LRU implementation of IDictionary?

Jak dodać rzeczy do słownika śledzić, które z nich, gdzie wykorzystywane najdawniej, usuń je z pamięci i utrzymywać tych na dysku.

2

Skompiluj dla 64 bitów, wdrażaj na 64 bitach, dodaj pamięć. Zachowaj to w pamięci.

Przed uprawą własną można ewentualnie spojrzeć na WeakReference http://msdn.microsoft.com/en-us/library/ms404247.aspx. Wymagałoby to oczywiście odbudowy tych obiektów, które zostały odzyskane, ale należy mieć nadzieję, że te, które są odzyskiwane, nie będą używane zbyt często. Jest to z zastrzeżeniem, że jego własne guidleiny stan uniknąć słabych odniesień jako automatycznego rozwiązania problemów zarządzania pamięcią.Zamiast tego należy opracować skuteczną strategię buforowania do obsługi obiektów aplikacji.

Oczywiście można zignorować tę wskazówkę i skutecznie obliczyć swój kod.

Można wdrożyć politykę buforowania, a po jej wygaśnięciu zapisać do bazy danych, pobrać pobieranie i pamięć podręczną. Wykorzystaj wygaśnięcia daty wygaśnięcia, ponieważ zależy ci na zachowaniu tych najczęściej używanych.

Pamiętaj jednak, że najczęściej używane i najcięższe to wyprzedaż. Utrata obiektu 10 razy dziennie, który zajmuje 5 minut, by przywrócić, drażniłaby użytkowników znacznie bardziej niż utratę obiektu 10000 razy, a narzędzie to zaledwie 5 ms, aby go przywrócić.

Ktoś wspomniał o pamięci podręcznej sieci. Robi to automatyczne zarządzanie pamięcią z odwołaniami, jak wspomniano, zależy, czy chcesz owijać ten w swoich aplikacjach.

I ... last but not least, spójrz na rozproszoną pamięć podręczną. Dzięki sharding możesz podzielić duży słownik na kilka maszyn.

Powiązane problemy