2013-01-09 21 views
10

Mam serwer django działający pod uwsgi, który wydaje się przeciekać pamięć.Zaskakujący wyciek pamięci poza pytaniem

W szczególności, RSS z procesów powoli rośnie, aż w końcu muszę go ponownie uruchomić.

Jestem świadomy innych podobnych pytań do tego, jednak wszystkie rozwiązania/wnioski znalezione do tej pory nie wydają się mieć zastosowania (które mogę znaleźć) w tym przypadku.

Dotychczas Użyłem meliae, Heapy, pympler i objgraph do wglądu sterty Python i wszyscy oni zgłosić to samo: normalny patrząc sterty stosując około 40MB pamięci (oczekiwane) z bardzo małej zmienności w czasie (jak pożądany).

Jest to niestety całkowicie niezgodne z procesem RSS, który na szczęście wzrośnie do 400 MB + z nie odbicie w wielkości sterty Pythona.

Niektóre przykładowe dane wyjściowe, aby zilustrować mój punkt widzenia -

wyjście Pympler porównując pyton kupie/przedmiot pamięci vs procesowego RSS:

Memory snapshot: 
             types | # objects | total size 
============================================= | =========== | ============ 
             dict |  20868 |  19852512 
              str |  118598 |  11735239 
             unicode |  19038 |  10200248 
             tuple |  58718 |  5032528 
             type |  1903 |  1720312 
             code |  13225 |  1587000 
             list |  11393 |  1289704 
          datetime.datetime |  6953 |  333744 
              int |  12615 |  302760 
    <class 'django.utils.safestring.SafeUnicode |   18 |  258844 
             weakref |  2908 |  255904 
    <class 'django.db.models.base.ModelState |  3172 |  203008 
        builtin_function_or_method |  2612 |  188064 
         function (__wrapper__) |  1469 |  176280 
             cell |  2997 |  167832 
          getset_descriptor |  2106 |  151632 
          wrapper_descriptor |  1831 |  146480 
              set |   226 |  143056 
             StgDict |   217 |  138328 
--------------------------- 
Total object memory: 56189 kB 
Total process usage: 
- Peak virtual memory size: 549016 kB 
- Virtual memory size: 549012 kB 
- Locked memory size: 0 kB 
- Peak resident set size: 258876 kB 
- Resident set size: 258868 kB 
- Size of data segment: 243124 kB 
- Size of stack segment: 324 kB 
- Size of code segment: 396 kB 
- Shared library code size: 57576 kB 
- Page table entries size: 1028 kB 
--------------------------- 

wyjściowy Heapy pokazując coś podobnego

Memory snapshot: 
Partition of a set of 289509 objects. Total size = 44189136 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 128384 44 12557528 28 12557528 28 str 
    1 61545 21 5238528 12 17796056 40 tuple 
    2 5947 2 3455896 8 21251952 48 unicode 
    3 3618 1 3033264 7 24285216 55 dict (no owner) 
    4 990 0 2570448 6 26855664 61 dict of module 
    5 2165 1 1951496 4 28807160 65 type 
    6 16067 6 1928040 4 30735200 70 function 
    7 2163 1 1764168 4 32499368 74 dict of type 
    8 14290 5 1714800 4 34214168 77 types.CodeType 
    9 10294 4 1542960 3 35757128 81 list 
<1046 more rows. Type e.g. '_.more' to view.> 
--------------------------- 
Total process usage: 
- Peak virtual memory size: 503132 kB 
- Virtual memory size: 503128 kB 
- Locked memory size: 0 kB 
- Peak resident set size: 208580 kB 
- Resident set size: 208576 kB 
- Size of data segment: 192668 kB 
- Size of stack segment: 324 kB 
- Size of code segment: 396 kB 
- Shared library code size: 57740 kB 
- Page table entries size: 940 kB 
--------------------------- 

Należy pamiętać, że w obu przypadkach raportowany rozmiar sterty to 40-50 MB, w podczas gdy proces RSS wynosi 200 MB +.

Mam również wykorzystywane objgraph za get_leaking_objects() próbować zobaczyć, czy C-extension robi złe ref liczenia, jednak liczba non-gc'able obiektów nie rośnie zwłaszcza w czasie.

Czy ktoś ma wgląd w to, jak rozwiązać ten problem? W tym momencie jestem zakładając jedną z dwóch rzeczy jest:

  • Mam C-extension wycieka pamięć wewnętrznie
  • uwsgi sama przecieka pamięci (choć mogę znaleźć żadnego innego dowodu to na netto)

Warto wspomnieć, że nie udało mi się odtworzyć tego w jakimkolwiek środowisku deweloperskim (choć możliwe, że nie wyrzucam na nie wystarczającej ilości ruchu).

Używamy wielu modułów, które mają rozszerzenia C (simplejson, hiredis, itp.), Więc jest zdecydowanie wiarygodne, że mogą być przyczyną.

Poszukuje metod, które należy podjąć, aby to sprawdzić.

+0

masz settings.py DEBUG = Fałsz, prawda? – monkut

+0

Tak, ale dobre pytanie :) – fenn

+0

Zastanawiałem się, czy w końcu rozwiązałeś ten problem? Mamy podobne problemy, które pojawiły się tylko od momentu przejścia na uwsgi. – Geekfish

Odpowiedz

2

Jakiej wersji Python używasz? W Pythonie 2.4 pamięć nie została zwrócona do systemu operacyjnego przez przydział pamięci Pythona.

W nowszych wersjach można zauważyć problem związany albo z alokatorem pamięci Pythona, który utrzymuje listy uwolnionych typów prostych, albo w przypadku, gdy korzystasz z Linuksa, problem nieodłącznie związany z tym, jak implementacja malloc w Glibc alokuje pamięć z systemu operacyjnego. Spójrz na http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm i http://pushingtheweb.com/2010/06/python-and-tcmalloc/.

+0

Python 2.6 (natywna wersja Ubuntu 10.04) w naszym przypadku. Zajrzę do sprawy malloc, jeszcze tego nie przebiegłem. – fenn