我有一个Python程序,该程序基本上保留list
个对象中的Counter
个,然后将它们写入磁盘。四天后,计数工作已经结束,但是系统的内存几乎已不足63GB,并且已经换出了50GB,没有任何进展。
这是我的代码的简化版本。
import os
import time
from collections import Counter
print(os.getpid())
counters = [Counter() for i in range(4)]
while True:
for i in range(1024):
for counter in counters:
counter[i] = 1
time.sleep(5)
with open('/tmp/counter.txt', 'w') as f:
for counter in counters:
f.write('\n'.join(map(str, counter.most_common())))
我猜它卡在了最后一行,因为它是OOM,所以无法对字典进行排序。
我需要将这些Counter
对象安全地写入磁盘以供以后处理
在其他线程中,我发现了some answers,但无法解决。这是我到目前为止尝试过的:
尝试腌制。转储Counter对象的可能候选对象
(gdb) bt
...
#21 0x0000000000504c28 in PyEval_EvalFrameEx (throwflag=0,
f=Frame 0x7f70a45d0cf8, for file /usr/lib/python3.6/collections/__init__.py, line 553, in most_common (self=<Counter at remote 0x7f70a2d7be60>, n=1048575)) at ../Python/ceval.c:4166
...
(gdb) python i = gdb.inferiors()[0]
(gdb) python m = i.read_memory(0x7f70a45d0cf8, 4)
(gdb) python print(m.tobytes())
b'\x02\x00\x00\x00'
(gdb) python import pickle
(gdb) python pickle.dump(m, open('/tmp/02.pickle', 'wb'))
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: can't pickle memoryview objects
Error while executing Python code.
(gdb) dump value 0x7f70a45d0cf8
No value to dump.
我不确定如何找到我感兴趣的对象的开始/结束地址。
答案 0 :(得分:0)
我找到了解决方案。
zcat /usr/share/doc/python3.6/gdbinit.gz > ~/.gdbinit
此gdbinit文件具有一个名为pyg的宏,该宏将对象的repr打印到stderr。
在同一文件中的pylocals会为框架中找到的每个本地调用此方法。
# gdb -p 12912
(gdb) bt
(gdb) f 21 # select relavant frame
(gdb) pylocals
这将这样的内容打印到Python程序控制台的stderr
object : [Counter({'foobar': 321}), Counter(), Counter(), Counter()]
type : list
refcount: 1
address : 0x7f02578ea5c8
对于我的真实代码,由于我要转储的对象很大,因此我暂停了Python程序并将其输出重定向到一个新文件。
fg &> gdb.out.pylocals.txt
我想这需要一些时间。
同时希望这对其他人也有帮助。