2009-01-09 7 views
34

Perl używa licznika referencji dla GC, i całkiem łatwo jest dokonać cyklicznego odniesienia przez przypadek. Widzę, że mój program wydaje się zużywać coraz więcej pamięci i prawdopodobnie wyleje się po kilku dniach.Jak mogę znaleźć wycieki pamięci w długo działającym programie Perla?

Czy istnieje sposób debugowania wycieków pamięci w Perlu? Przywiązanie do programu i uzyskanie liczby obiektów różnych typów byłoby dobrym początkiem. Gdybym wiedział, które obiekty są znacznie liczniejsze niż oczekiwano, mógłbym sprawdzić wszystkie odniesienia do nich i, miejmy nadzieję, naprawić wyciek.

Odpowiedz

34

To może być istotne, że Perl nigdy nie przywraca pamięci do systemu: Wszystko zależy od malloc() i wszystkich zasad z tym związanych.

Wiedząc, jak malloc() alokuje pamięć jest ważne, aby odpowiedzieć na pytanie większe, a to zależy od systemu, ale generalnie większość malloc() implementacje są zoptymalizowane dla programów przydzielania i dealokując zamówień Stack podobne. Perl używa licznika odwołań do śledzenia pamięci, co oznacza, że ​​deallokacje oznaczają (w przeciwieństwie do języka opartego na GC, który używa malloc() pod), w rzeczywistości nie jest to wcale trudne, aby dokonać deallokacji iw jakiej kolejności.

może być tak, że można zreorganizować swój program, aby skorzystać z tej fact- wywołując undef($old_object) wyraźnie - i we właściwej kolejności, w sposób podobny do sposobu C-programiści mówią free(old_object);

Dla długo- uruchomione programy (dni, miesiące, itp.), gdzie mam mnóstwo cykli ładowania/kopiowania/zrzucania, zbieram śmieci używając exit() and exec(), a gdzie jest to niemożliwe na całym świecie, po prostu pakuję moje struktury danych (używając Storable) i deskryptorów plików (przy użyciu $^F) i exec($0) - zazwyczaj ze zmienną środowiskową ustawioną jako $ENV{EXEC_GC_MODE}, a może być potrzebna coś podobnego pod warunkiem, że nie ma żadnych takich samych , nawet jeśli nie masz żadnych przecieki twojego własnego po prostu dlatego, że Perl przecieka małe kawałki, że twój system malloc() nie może dowiedzieć się, jak oddać.

Oczywiście, jeśli masz przecieki w swój kod, to reszta mojej porady jest nieco bardziej istotne. Pierwotnie został opublikowany to another question on this subject, ale nie był to jawnie obejmujący długo działające programy.


Wszystkie wycieki pamięci programu perl będą albo przenoszeniem XS na referencję, albo kołową strukturą danych. Devel::Cycle to doskonałe narzędzie do wyszukiwania odwołań cyklicznych, jeśli wiesz, jakie struktury mogą zawierać pętle. Devel::Peek można użyć do znalezienia obiektów o wyższej od oczekiwanej liczbie odwołań.

Jeśli nie wiesz, gdzie jeszcze szukać, Devel::LeakTrace::Fast może być dobrym pierwszym miejscem, ale będziesz potrzebować perla stworzonego do debugowania.

Jeśli podejrzewasz, że wyciek znajduje się w przestrzeni XS, jest to znacznie trudniejsze, a prawdopodobnie najlepszym rozwiązaniem będzie Valgrind. Test::Valgrind może pomóc ci zmniejszyć ilość kodu, który musisz przeszukać, ale to nie zadziała w Windowsie, więc będziesz musiał przenieść (przynajmniej nieszczelną część) do Linuksa, aby to zrobić.

+0

http://search.cpan.org/perldoc?Scalar::Util 'osłabienie' –

+0

Jak pomaga ci "osłabić"? – geocar

+0

@geocar, to jest genialne! Jedyną niezawodną metodą nieuniknionego problemu wycieków pamięci w złożonych programach perlowych, które znam. –

3

Wygląda na to, że moduł cpan Devel::Cycle jest tym, czego szukasz. Wymaga wprowadzenia pewnych zmian w kodzie, ale powinno pomóc w znalezieniu referencji bez zbyt wielu problemów.

2

to świetna aplikacja dla systemu Linux, która lokalizuje wycieki pamięci w uruchomionym kodzie. Jeśli Twój kod Perla działa na Linuksie, powinieneś to sprawdzić.

+0

Nie sądzę, że to zadziała. Perl jest językiem interpretowanym. Czy valgrind nie wskaże tylko wywołań alokacji pamięci w interpretera Perla? – Ferruccio

+0

no valgrind może pracować z Perlem, wystarczy użyć odpowiednich opcji. to jest udokumentowane. musi dołączyć się do skompilowanego pliku wykonywalnego, a nie pliku binarnego perla. – casey

+0

valgrind znajdzie wycieki pamięci w kodzie XS, ale nie w kodzie Perla. Użyj Devel :: Cycle lub Devel :: Leak za to. – rjh

2

Oprócz innych komentarzy, może okazać się użyteczny mój Perl Memory Use talk na LPW2013. Polecam oglądanie the screencast, ponieważ wyjaśnia slajdy i ma kilka uroczych wizualizacji i niektóre Q & A na końcu.

Proponuję również przejrzenie modułu Paul Evans Devel::MAT, o którym wspominałem w wykładzie.