10

メモリリークしているように見える uwsgi で実行されている django Web サーバーがあります。

具体的には、プロセスの RSS がゆっくりと大きくなり、最終的に再起動する必要があります。

これと同様の質問が他にもあることは認識していますが、これまでに見つかったすべての解決策/結論は、この場合には適用されないようです (私が見つけることができます)。

これまでのところ、meliaeHeapypympler、およびobjgraphを使用して python ヒープを検査しましたが、それらはすべて同じことを報告しています: 約 40MB のメモリを使用する通常の外観のヒープ (予想) で、時間の経過による変動がほとんどありません (必要に応じて)。

残念ながら、これはプロセス RSS と完全に一致しません。RSSは、python ヒープ サイズに反映されずに 400MB 以上まで喜んで拡大します。

私の要点を説明するための出力例-

Python ヒープ/オブジェクト メモリとプロセス RSS を比較した Pympler 出力:

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
---------------------------

同様のことを示す大量の出力

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
---------------------------

どちらの場合も、報告されたヒープ サイズは 40 ~ 50MB であるのに対し、プロセスの RSS は 200MB 以上であることに注意してください。

また、objgraph のget_leaking_objects()を使用して、C 拡張機能が不適切な参照カウントを行っているかどうかを確認しようとしましたが、gc できないオブジェクトの数は時間の経過とともに著しく増加しません。

これをデバッグする方法について誰か洞察がありますか? この時点で、次の 2 つのいずれかが当てはまると推測しています。

  • 内部でメモリをリークする C 拡張機能があります
  • uwsgi 自体がメモリ リークを起こしています (ただし、これに関する他の証拠はネット上で見つかりません)。

これをどのような種類の開発環境でも複製することに成功しなかったことに言及する価値があるかもしれません (ただし、十分なトラフィックをそれらに投げていない可能性があります)。

私たちは C 拡張 (simplejson、hiredis など) を持つ多数のモジュールを使用しているため、それらが原因である可能性は間違いなくあります。

これを追跡するためのアプローチを探しています。

4

1 に答える 1

2

Python のどのバージョンを使用していますか? Python 2.4 では、メモリは Python メモリ アロケータによって OS に返されませんでした。

まだ新しいバージョンでは、解放された単純型のリストを保持する Python のメモリ アロケータに関連する問題、または Linux で実行している場合は、glibc の malloc 実装が OS からメモリを割り当てる方法に固有の問題が見られます。http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htmおよびhttp://pushingtheweb.com/2010/をご覧ください。 06/python-and-tcmalloc/ .

于 2013-01-09T09:01:46.067 に答える