Python のgc
ガベージ コレクター インターフェイスを使用sys.getsizeof()
すると、すべての Python オブジェクトとそのサイズをダンプできます。メモリリークをトラブルシューティングするために本番環境で使用しているコードは次のとおりです。
rss = psutil.Process(os.getpid()).get_memory_info().rss
# Dump variables if using more than 100MB of memory
if rss > 100 * 1024 * 1024:
memory_dump()
os.abort()
def memory_dump():
dump = open("memory.pickle", 'wb')
xs = []
for obj in gc.get_objects():
i = id(obj)
size = sys.getsizeof(obj, 0)
# referrers = [id(o) for o in gc.get_referrers(obj) if hasattr(o, '__class__')]
referents = [id(o) for o in gc.get_referents(obj) if hasattr(o, '__class__')]
if hasattr(obj, '__class__'):
cls = str(obj.__class__)
xs.append({'id': i, 'class': cls, 'size': size, 'referents': referents})
cPickle.dump(xs, dump)
属性を持つオブジェクトからのデータのみを保存していることに注意してください__class__
。これは、私が気にする唯一のオブジェクトであるためです。オブジェクトの完全なリストを保存できるはずですが、他の属性の選択には注意が必要です。また、各オブジェクトのリファラーを取得するのが非常に遅いことがわかったので、リファレントのみを保存することにしました。とにかく、クラッシュの後、結果のピクルされたデータは次のように読み戻すことができます:
with open("memory.pickle", 'rb') as dump:
objs = cPickle.load(dump)
2017-11-15 追加
Python 3.6 バージョンは次のとおりです。
import gc
import sys
import _pickle as cPickle
def memory_dump():
with open("memory.pickle", 'wb') as dump:
xs = []
for obj in gc.get_objects():
i = id(obj)
size = sys.getsizeof(obj, 0)
# referrers = [id(o) for o in gc.get_referrers(obj) if hasattr(o, '__class__')]
referents = [id(o) for o in gc.get_referents(obj) if hasattr(o, '__class__')]
if hasattr(obj, '__class__'):
cls = str(obj.__class__)
xs.append({'id': i, 'class': cls, 'size': size, 'referents': referents})
cPickle.dump(xs, dump)