11/12/2009

Ciekawe zgłoszenie błędu

Home

Jest to druga, poprawiona wersja tego postu. Za wcześniejsze pomyłki przepraszam.

W poście tym chciałbym opisać interesujący błąd. Wszystko zaczęło się od zgłoszenia od klienta dotyczącego problemów z wydrukami. Nie wchodząc w szczegóły okazało się, że cały problem sprowadza się do utworzenia dostatecznie dużej bitmapy. Co jednak ciekawe analiza pokazała, że system dysponuje znaczną ilością wolnej pamięci (ok 1.5 GB) podczas gdy do utworzenia bitmapy potrzebne było "raptem" kilkaset megabajtów. Tutaj dodam, że mówimy o systemie 32 bitowym.

Z pomocą przyszedł tutaj program vnmap, który służy do analizy pamięci wirtualnej i fizycznej procesu. Pokazał on, że proces rzeczywiście dysponuje znaczną ilością pamięci ale największy ciągły jej obszar to tylko 200 MB. Do zaalokowania bitmapy potrzeba natomiast właśnie ciągłego obszaru pamięci. Nie dotyczy to zresztą tylko bitmap, podobny problem możemy wystąpić przy ładowaniu bibliotek dll.

Taką sytuację nazywamy defragmentacją pamięci. Co było jej przyczyną? Zgodnie z tym co pokazał wspomniany program vnamp pamięć w dużym stopniu była poszatkowana przez biblioteki dynamiczne. Nie bez znaczenia jest tutaj fakt, że rozpatrywany przypadek dotyczył dość dużego systemu zbudowanego z wielu modułów.

Problem próbowałem zaleczyć przy użyciu narzędzia rebase.exe, które służy do ustawienia preferowanego adresu pod jaki ma zostać załadowana dll'ka. Testy niestety pokazały, że to nic nie daje.

Pytanie co jest przyczyną takiego położenia bibliotek w pamięci? Tutaj nie pozostaje mi nic innego jak rozłożyć ręce. Wcześniej byłem przekonany, że jest to związane z mechanizmem bezpieczeństwa, który losowo rozrzuca biblioteki po pamięci. Zwrócono mi jednak uwagę, że taki mechanizm (ASLR) pojawił się dopiero w Windows Vista. Sprawa jest więc otwarta. Jakieś pomysły?

Jak sobie z tym poradzić? Generalnie jednoznacznej odpowiedzi nie ma, ja znam trzy podejścia. Po pierwsze przejście na system 64 bitowy rozwiąże problem ale nie jest to zawsze możliwe. Po drugie można próbować wyeliminować konieczność alokacji tak dużej bitmapy ale może to być bardzo trudne. Można też użyć przełącznika /3GB, który pozwala procesom użytkownika użyć 3 GB pamięci wirtualnej zamiast domyślnych 2 GB ale nie jest to zalecane rozwiązanie.

Na zakończenie chciałbym podziękować koledze Damianowi z pracy, który analizował zgłoszenie klienta i podsunął mi pomysł na ten post.

6 comments:

Komodo said...

Skąd pomysł, że przyczyną tej sytuacji był "mechanizm bezpieczeństwa"? Poza tym ASLR wprowadzony zostało dopiero od Visty.

Michał Komorowski said...

Witam

Oczywiście masz rację, że ASLR (przynajmniej pod taką nazwą) pojawił się dopiero w Windows Vista. Z drugiej jednak strony obserwowane poszatkowanie pamięci przez dll'ki oraz to, że narzędzie rebase nie chciało działać jest bardzo zastanawiające. Niestety w tej chwili nie potrafię znaleźć w sieci oficjalnego potwierdzenia moich przypuszczeń i jest to tylko mój błąd. Dziękuję za zwrócenie uwagi, naniosłem odpowiednie poprawki w poście.

reichel said...

Zawsze mozna pofragmentowac bitmape. Klasa by udostepniala to co zwykla ale w pamieci byla by podzielona na 2/4/8/ ... Oczywiscie o ile mamy dostep do tworzenia bitmapy (tj. nasza praca).
Niezbyt latwe (szczegolnie rysowanie jakis obiektow jak kolo - trzeba podzielic najpierw na luki i liczyc ze algorytm ladnie zgra je na granicach pozdialu).

ale to odrobina bezsensu jak na dzisiejsze czay

Anonymous said...

Kiedyś czytałem o zjawisku nazywanym "Large Object Heap". Problem, który wtedy miałem był podobny do opisywanego - szukałem przyczyn występowania wyjątków podczas tworzenia w usłudze bardzo dużej liczby faktur (faktury były generowane w pamięci - tworzone były masowo duże obiekty, które oczywiście były zwalniane). Okazało się jednak, że po dłuższej pracy aplikacja zamierała. Sądziłem, że to właśnie LOH - brak jest jednoznacznego rozwiązania tego problemu chyba do dziś. Okazało się jednak, że błąd był w module ReportViewer (używanym w tym procesie, który niestety nie zwalniał pamięci prawidłowo). Pisałem na Microsoft Connect, ale nic z tym nie zrobiono wtedy... Generalnie takie aplikacje jak Paint.NET jakoś sobie radzą z dużymi bitmapami, więc nie wiem, czy LOH powoduje duże problemy w aplikacjach. Bardzo ciekawa sprawa jest z tą defragmentacją pamięci. Napisz czy udało się rozwiązać ten problem. Pozdr.

Michał Komorowski said...
This comment has been removed by the author.
Michał Komorowski said...

W obecnej chwili nie pracuję już przy projekcie, przy którym wystąpił błąd - zmiana pracy ;) Mogę tylko powiedzieć, że jeszcze za moich czasów zdecydowano się zmienić technologię na nowszą i z tego co wiem w tej chwili trwają nad tym pracę. Pierwotnie aplikacja, w której występował błąd napisana była przy użyciu starej technologii firmy ESRI - MapObjects. Nowa technologia nazywa się natomiast ArcGIS Engine i daje dużo więcej możliwości. Z testów jakie przeprowadziłem wynika, że radzi sobie z wydrukiem bardzo dużych bitmap.

Post a Comment