Pisałem C ++ przez 10 lat. Napotkałem problemy z pamięcią, ale można je było naprawić przy rozsądnym wysiłku.
Od kilku lat piszę w C #. Wciąż mam wiele problemów z pamięcią. Są trudne do zdiagnozowania i naprawienia ze względu na brak determinanty, a ponieważ filozofia C # polega na tym, że nie powinieneś się martwić o takie rzeczy, gdy zdecydowanie to robisz.
Jednym ze szczególnych problemów jest to, że muszę jawnie usunąć i wyczyścić wszystko w kodzie. Jeśli tego nie zrobię, to profilery pamięci tak naprawdę nie pomogą, ponieważ jest tak dużo plew, że nie możesz znaleźć wycieku we wszystkich danych, które próbują ci pokazać. Zastanawiam się, czy mam zły pomysł, czy też narzędzie, które mam, nie jest najlepsze.
Jakie strategie i narzędzia są przydatne do rozwiązywania problemów z wyciekami pamięci w .NET?
źródło
Odpowiedzi:
Używam MemProfiler firmy Scitech, gdy podejrzewam wyciek pamięci.
Jak dotąd stwierdziłem, że jest bardzo niezawodny i potężny. Przynajmniej raz uratował mi boczek.
GC działa bardzo dobrze w .NET IMO, ale tak jak każdy inny język lub platforma, jeśli napiszesz zły kod, zdarzają się złe rzeczy.
źródło
W przypadku problemu z zapominaniem o usunięciu wypróbuj rozwiązanie opisane w tym poście na blogu . Oto istota:
źródło
W naszym projekcie wykorzystaliśmy oprogramowanie Ants Profiler Pro firmy Red Gate. Działa bardzo dobrze we wszystkich aplikacjach opartych na języku .NET.
Odkryliśmy, że .NET Garbage Collector jest bardzo „bezpieczny” w czyszczeniu obiektów w pamięci (tak jak powinno). Utrzymywałoby obiekty w pobliżu tylko dlatego, że moglibyśmy go kiedyś używać w przyszłości. Oznaczało to, że musieliśmy bardziej uważać na liczbę obiektów, które napompowaliśmy w pamięci. Ostatecznie przekonwertowaliśmy wszystkie nasze obiekty danych na „inflację na żądanie” (tuż przed żądaniem pola), aby zmniejszyć obciążenie pamięci i zwiększyć wydajność.
EDYCJA: Oto dalsze wyjaśnienie, co mam na myśli, mówiąc o „nadmuchaniu na żądanie”. W naszym modelu obiektowym naszej bazy danych używamy właściwości obiektu nadrzędnego, aby wyeksponować obiekt (y) potomne. Na przykład, gdybyśmy mieli jakiś rekord, który odnosił się do jakiegoś innego „szczegółu” lub „wyszukiwania” na zasadzie jeden do jednego, utworzylibyśmy taką strukturę:
Odkryliśmy, że powyższy system powodował pewne problemy z pamięcią i wydajnością, gdy w pamięci było dużo rekordów. Dlatego przeszliśmy na system, w którym obiekty były nadmuchiwane tylko wtedy, gdy były wymagane, a wywołania bazy danych były wykonywane tylko wtedy, gdy było to konieczne:
Okazało się to znacznie bardziej wydajne, ponieważ obiekty były przechowywane poza pamięcią, dopóki nie były potrzebne (uzyskano dostęp do metody Get). Zapewnił bardzo duży wzrost wydajności w ograniczaniu trafień w bazie danych i ogromny przyrost miejsca w pamięci.
źródło
Nadal musisz martwić się o pamięć podczas pisania kodu zarządzanego, chyba że aplikacja jest trywialna. Zasugeruję dwie rzeczy: najpierw przeczytaj CLR przez C #, ponieważ pomoże ci to zrozumieć zarządzanie pamięcią w .NET. Po drugie, naucz się korzystać z narzędzia takiego jak CLRProfiler (Microsoft). To może dać ci wyobrażenie o tym, co powoduje wyciek pamięci (np. Możesz przyjrzeć się fragmentacji sterty dużych obiektów)
źródło
Czy używasz niezarządzanego kodu? Jeśli nie używasz kodu niezarządzanego, według Microsoft przecieki pamięci w tradycyjnym sensie nie są możliwe.
Pamięć używana przez aplikację może jednak nie zostać zwolniona, więc alokacja pamięci aplikacji może rosnąć w trakcie jej życia.
Aby poradzić sobie z tego typu problemami, możesz zaimplementować IDisposable . Jeśli chcesz zobaczyć niektóre strategie radzenia sobie z zarządzaniem pamięcią, sugerowałbym wyszukanie IDisposable, XNA, zarządzanie pamięcią, ponieważ twórcy gier muszą mieć bardziej przewidywalne zbieranie śmieci, a więc muszą zmusić GC do zrobienia tego.
Częstym błędem jest nieusuwanie programów obsługi zdarzeń, które subskrybują obiekt. Subskrypcja programu obsługi zdarzeń uniemożliwi ponowne odtworzenie obiektu. Przyjrzyj się również instrukcji using , która umożliwia utworzenie ograniczonego zakresu czasu życia zasobu.
źródło
Ten blog zawiera naprawdę wspaniałe instrukcje korzystania z windbg i innych narzędzi do śledzenia wszelkiego rodzaju wycieków pamięci. Doskonała lektura, aby rozwinąć swoje umiejętności.
źródło
Właśnie miałem wyciek pamięci w usłudze systemu Windows, który naprawiłem.
Najpierw wypróbowałem MemProfiler . Uważam, że jest naprawdę trudny w użyciu i wcale nie jest przyjazny dla użytkownika.
Następnie użyłem JustTrace, który jest łatwiejszy w użyciu i daje więcej szczegółów na temat obiektów, które nie są prawidłowo usuwane.
Pozwoliło mi to naprawdę łatwo rozwiązać problem wycieku pamięci.
źródło
Jeżeli przecieki obserwujesz są ze względu na uciekający realizacji pamięci podręcznej, to jest scenariusz, w którym może warto rozważyć użycie WeakReference. Może to pomóc w zapewnieniu zwolnienia pamięci, gdy jest to konieczne.
Jednak w IMHO lepiej byłoby rozważyć indywidualne rozwiązanie - tylko Ty naprawdę wiesz, jak długo musisz przechowywać obiekty w pobliżu, więc zaprojektowanie odpowiedniego kodu porządkowego dla Twojej sytuacji jest zwykle najlepszym podejściem.
źródło
Wolę dotmemory od Jetbrains
źródło
Big guns - narzędzia do debugowania dla systemu Windows
To niesamowita kolekcja narzędzi. Za jego pomocą można analizować zarówno zarządzane, jak i niezarządzane sterty i można to robić w trybie offline. Było to bardzo przydatne w przypadku debugowania jednej z naszych aplikacji ASP.NET, która była odtwarzana z powodu nadmiernego wykorzystania pamięci. Musiałem tylko stworzyć pełny zrzut pamięci żywego procesu działającego na serwerze produkcyjnym, cała analiza została wykonana offline w WinDbg. (Okazało się, że jakiś programista nadużywał pamięci masowej sesji w pamięci).
Blog „Jeśli zepsuty to…” zawiera bardzo przydatne artykuły na ten temat.
źródło
Najlepszą rzeczą, o której należy pamiętać, jest śledzenie odniesień do obiektów. Bardzo łatwo jest skończyć z wiszącymi odnośnikami do obiektów, na których już Ci nie zależy. Jeśli nie zamierzasz już czegoś używać, pozbądź się tego.
Przyzwyczaj się do korzystania z dostawcy pamięci podręcznej z ruchomymi okresami ważności, więc jeśli coś nie jest przywoływane w żądanym oknie czasowym, zostanie wyłuskane i wyczyszczone. Ale jeśli jest często używany, powie to w pamięci.
źródło
Jednym z najlepszych narzędzi jest użycie narzędzi debugowania dla systemu Windows i wykonanie zrzutu pamięci procesu za pomocą adplus , a następnie użycie windbg i wtyczki sos do analizy pamięci procesu, wątków i stosów wywołań.
Możesz użyć tej metody do identyfikowania problemów na serwerach, po zainstalowaniu narzędzi, udostępnij katalog, a następnie połącz się z udziałem z serwera za pomocą (użycie sieci) i albo zawieszaj się, albo zawieszaj zrzut procesu.
Następnie przeanalizuj offline.
źródło
Po jednej z moich poprawek dla zarządzanej aplikacji miałem to samo, na przykład jak sprawdzić, czy moja aplikacja nie będzie miała takiego samego wycieku pamięci po mojej następnej zmianie, więc napisałem coś w rodzaju struktury weryfikacji wydania obiektu, spójrz na pakiet Nuget ObjectReleaseVerification . Próbkę można znaleźć tutaj https://github.com/outcoldman/OutcoldSolutions-ObjectReleaseVerification-Sample oraz informacje o tym przykładzie http://outcoldman.ru/en/blog/show/322
źródło
W programie Visual Studio 2015 rozważ użycie gotowego narzędzia diagnostycznego użycia pamięci do zbierania i analizowania danych o użyciu pamięci.
Narzędzie Użycie pamięci umożliwia wykonanie jednej lub więcej migawek zarządzanej i natywnej sterty pamięci w celu zrozumienia wpływu użycia pamięci na typy obiektów.
źródło
jedno z najlepszych narzędzi, z których korzystałem, DotMemory. możesz użyć tego narzędzia jako rozszerzenia w VS. po uruchomieniu aplikacji możesz przeanalizować każdą część pamięci (według obiektu, NameSpace itp.), z której korzysta Twoja aplikacja i zrobić migawkę tego , Porównaj to z innymi SnapShotami. DotMemory
źródło