Jak rozwiązać fragmentację pamięci

Od czasu do czasu pojawiają się problemy, w wyniku których nasze długotrwałe procesy serwerowe (działające w systemie Windows Server 2003) wyrzuciły wyjątek z powodu awarii alokacji pamięci. Podejrzewamy, że te przydziały nie działają z powodu fragmentacji pamięci.

Dlatego szukaliśmy alternatywnych mechanizmów alokacji pamięci, które mogą nam pomóc i mam nadzieję, że ktoś powie mi najlepszy:

1) Use Windows Low-fragmentation Heap

2) jemalloc-używany w Firefox 3

3) malloc

Nasz proces serwera jest rozwijany przy użyciu wieloplatformowego kodu C++, więc każde rozwiązanie byłoby idealnie międzyplatformowe również (czy * nix systemy operacyjne cierpią z powodu tego typu fragmentacji pamięci?).

Również, czy mam rację w myśleniu, że LFH jest teraz domyślnym mechanizmem alokacji pamięci Dla Windows Server 2008 / Vista?... Czy moje obecne problemy "znikną", jeśli nasi klienci po prostu uaktualnią swoje Server os?

Author: Alan, 2008-09-14

9 answers

Po pierwsze, zgadzam się z innymi plakatami, którzy sugerowali wyciek zasobów. Naprawdę chcesz to najpierw wykluczyć.

Miejmy nadzieję, że menedżer stosu, którego aktualnie używasz, ma sposób na zrzut rzeczywistej całkowitej wolnej przestrzeni dostępnej w stosie (we wszystkich wolnych blokach), a także całkowitą liczbę bloków, na które jest podzielony. Jeśli średni rozmiar wolnego bloku jest stosunkowo mały w porównaniu do całkowitej wolnej przestrzeni w stercie, to masz problem fragmentacji. Alternatywnie, jeśli możesz zrzucić rozmiar największego wolnego bloku i porównać go z całkowitą wolną przestrzenią, to osiągniesz to samo. Największy wolny blok byłby mały w stosunku do całkowitej free przestrzeń dostępna we wszystkich blokach w przypadku fragmentacji.

Żeby było jasne co do powyższego, we wszystkich przypadkach mówimy o free bloki w stercie, a nie przydzielone bloki w stercie. W każdym razie, jeśli powyższe warunki nie są spełnione, wtedy masz jakąś sytuację wycieku.

Więc, po wykluczeniu przecieku, można rozważyć użycie lepszego alokatora. malloc Douga Lea sugerowany w pytaniu jest bardzo dobrym alokatorem do zastosowań ogólnych i bardzo solidnym większości czasu. Mówiąc inaczej, został przetestowany w czasie, aby działał bardzo dobrze dla większości aplikacji. Jednak żaden algorytm nie jest idealny dla wszystkich aplikacji i wszelkich podejście algorytmu zarządzania może zostać złamane przez właściwe warunki patologiczne względem jego konstrukcji.

Dlaczego masz problem z fragmentacją? - źródła problemów z fragmentacją są spowodowane przez zachowanie aplikacji i mają do czynienia z bardzo różnymi okresami alokacji na tej samej arenie pamięci. Oznacza to, że niektóre obiekty są przydzielane i zwalniane regularnie, podczas gdy inne typy obiektów utrzymują się przez dłuższy czas w tej samej stercie.....pomyśl o te o dłuższej żywotności, jak wbijanie otworów w większe obszary areny, a tym samym zapobieganie połączeniu sąsiednich bloków, które zostały uwolnione.

Aby rozwiązać ten typ problemu, najlepszą rzeczą, jaką możesz zrobić, to logicznie podzielić stertę na sub areny, w których życia są bardziej podobne. W efekcie chcesz mieć stos przejściowy i stos trwały lub stos, które grupują rzeczy o podobnym okresie życia.

Niektórzy zaproponowali inne podejście do rozwiązania problemu, jakim jest staraj się, aby rozmiar alokacji był bardziej podobny lub identyczny, ale jest to mniej idealne, ponieważ tworzy inny rodzaj fragmentacji zwany fragmentacją wewnętrzną - która jest w efekcie marnowaną przestrzenią, którą masz, przydzielając więcej pamięci w bloku niż potrzebujesz.

Dodatkowo, przy dobrym alokatorze sterty, takim jak Doug Lea, nie jest konieczne, aby rozmiary bloków były bardziej podobne, ponieważ alokator będzie już robił schemat bucketingu o dwóch rozmiarach, który sprawi, że będzie to całkowicie niepotrzebne sztucznie dostosowywanie wielkości alokacji przekazywanych do malloc() - w efekcie jego menedżer stosów robi to za ciebie automatycznie znacznie bardziej solidnie, niż aplikacja będzie w stanie dokonać korekt.

 33
Author: Tall Jeff,
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
2014-05-05 19:47:52

Chyba za wcześnie wykluczyłeś wyciek pamięci. Nawet niewielki wyciek pamięci może spowodować poważną fragmentację pamięci.

Zakładając, że aplikacja zachowuje się następująco:
Przeznaczyć 10MB
Przydziel 1 bajt
Free 10MB
(UPS, nie zwolniliśmy 1 bajtu, ale kogo obchodzi 1 malutki bajt)

Wygląda to na bardzo mały wyciek, prawie go nie zauważysz, monitorując tylko całkowity rozmiar przydzielonej pamięci . Ale ten przeciek w końcu spowoduje twoja pamięć aplikacji wygląda tak:
.
.
Free-10MB
.
.
[Przydzielone -1 bajt]
.
.
Free-10MB
.
.
[Przydzielone -1 bajt]
.
.
Free-10MB
.
.

Ten wyciek nie zostanie zauważony... dopóki nie chcesz przeznaczyć 11MB
Zakładając, że Twoje minidumpy miały pełne informacje o pamięci, zalecam użycie DebugDiag , aby wykryć możliwe wycieki. W wygenerowanym raporcie pamięci dokładnie zbadaj liczba alokacji (Nie rozmiar) .

 15
Author: Tal,
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-04-29 09:07:57

Jak sugerujesz, malloc Douga Lea może się udać. Jest wieloplatformowy i został użyty w kodzie wysyłkowym. Co najmniej, integracja z kodem powinna być łatwa do przetestowania.

Pracując w środowiskach pamięci stałej przez wiele lat, ta sytuacja jest z pewnością problemem, nawet w środowiskach Nie stałych. Odkryliśmy, że alokatory CRT mają tendencję do śmierdzenia dość źle pod względem wydajności (szybkość, wydajność zmarnowanej przestrzeni itp.). Mocno wierzę, że jeśli masz duże zapotrzebowanie na dobry alokator pamięci przez długi okres czasu, powinieneś napisać swój własny (lub sprawdzić, czy coś takiego jak dlmalloc zadziała). Sztuką jest napisanie czegoś, co działa z wzorcami alokacji i ma więcej wspólnego z wydajnością zarządzania pamięcią, jak prawie wszystko inne.

Spróbuj dlmalloc. Zdecydowanie daję mu kciuki w górę. Jest również dość przestrajalny, więc możesz być w stanie uzyskać większą wydajność, zmieniając część czasu kompilacji opcje.

Szczerze mówiąc, nie powinieneś polegać na tym, że rzeczy "odejdą" z nowymi implementacjami systemu operacyjnego. Service pack, patch lub inny nowy OS N lata później może pogorszyć problem. Ponownie, w przypadku aplikacji, które wymagają solidnego Menedżera pamięci, nie używaj wersji zapasowych, które są dostępne z kompilatorem. Znajdź taki, który pasuje do Twojej sytuacji. Zacznij od dlmalloc i dostroić go, aby zobaczyć, czy można uzyskać zachowanie, które działa najlepiej dla twojej sytuacji.

 5
Author: Mark,
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
2008-09-14 02:21:08

Możesz pomóc zmniejszyć fragmentację, zmniejszając ilość przydzielanych deallocate.

Np. powiedzmy, że serwer WWW z skryptem po stronie serwera może utworzyć ciąg znaków, do którego będzie wyświetlana strona. Zamiast przydzielać i dealokować te ciągi dla każdego żądania strony, po prostu utrzymuj ich pulę, więc przydzielasz tylko wtedy, gdy potrzebujesz więcej, ale nie dealokujesz (co oznacza, że po pewnym czasie pojawi się sytuacja, w której już nie przydzielasz, ponieważ masz wystarczająco dużo)

Ty można użyć _CrtDumpMemoryLeaks (); do zrzutu wycieków pamięci do okna debugowania podczas uruchamiania kompilacji debugowania, jednak uważam, że jest to specyficzne dla kompilatora Visual C. (jest w crtdbg.h)

 2
Author: Fire Lancer,
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
2015-03-31 06:33:53

Podejrzewałbym przeciek, zanim podejrzewałbym fragmentację.

W przypadku struktur danych wymagających dużej ilości pamięci można przełączyć się na mechanizm puli pamięci wielokrotnego użytku. Możesz również być w stanie przeznaczyć więcej rzeczy na stosie, w przeciwieństwie do sterty, ale w praktyce, że nie będzie to wielka różnica, myślę.

Odpaliłbym narzędzie takie jak valgrind lub zrobił intensywne logowanie, aby szukać zasobów, które nie są zwolnione.

 1
Author: nsanders,
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
2008-09-13 21:10:38

@nsaners-jestem prawie pewien, że problem sprowadza się do fragmentacji pamięci. Przeanalizowaliśmy minidumpy , które wskazują na problem, gdy przydzielany jest duży (5-10mb) kawałek pamięci. Monitorowaliśmy również proces (na miejscu i w fazie rozwoju), aby sprawdzić wycieki pamięci - żaden nie został wykryty (ślad pamięci jest na ogół dość niski).

 1
Author: Alan,
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
2008-09-13 21:28:44

Problem zdarza się na Uniksie, chociaż zazwyczaj nie jest tak źle.

Sterta niskich kadrów nam pomogła, ale moi współpracownicy przeklinają inteligentną stertę (od lat jest używany na wielu platformach w kilku naszych produktach). Niestety z powodu innych okoliczności nie mogliśmy tym razem użyć Smart Heap.

Przyglądamy się również alokacji bloków/chunkingu i próbom posiadania puli/strategii zorientowanych na zakres, tj., długoterminowe rzeczy tutaj, całe prośby tam, krótkoterminowe rzeczy tam, itp.

 1
Author: maccullt,
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
2008-09-13 21:59:32

Jak zwykle, można zwykle marnować pamięć, aby zyskać trochę prędkości.

Ta technika nie jest przydatna dla alokatora ogólnego przeznaczenia, ale ma swoje miejsce.

Zasadniczo chodzi o to, aby napisać alokator, który zwraca pamięć z puli, w której wszystkie alokacje mają ten sam rozmiar. Ta pula nigdy nie może zostać rozdrobniona, ponieważ każdy blok jest tak dobry jak inny. Możesz zmniejszyć straty pamięci, tworząc wiele pul z kawałkami o różnych rozmiarach i wybierając najmniejszy rozmiar Pula, która jest nadal większa niż żądana kwota. Użyłem tego pomysłu do stworzenia alokatorów, które działają w O(1).

 1
Author: dicroce,
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
2008-09-13 22:55:00

Jeśli mówisz o Win32 - możesz spróbować wycisnąć coś używając LARGEADDRESSAWARE. Będziesz miał ~1GB dodatkowej defragmentowanej pamięci, więc aplikacja będzie fragmentować go dłużej.

 -1
Author: Serov Danil,
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
2016-11-29 11:09:32