本程序现状如下:
(Pdb) h0 = hp.heap()
(Pdb) h0
Partition of a set of 4254865 objects. Total size = 700955416 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 646764 15 427504800 61 427504800 61 dict (no owner)
1 3073581 72 210210328 30 637715128 91 unicode
2 120775 3 17186360 2 654901488 93 list
3 71772 2 10795432 2 665696920 95 str
4 37269 1 10594328 2 676291248 96 _sre.SRE_Pattern
5 124398 3 10406784 1 686698032 98 tuple
6 721 0 2114200 0 688812232 98 dict of module
7 83485 2 2003640 0 690815872 99 int
8 11706 0 1498368 0 692314240 99 types.CodeType
9 11157 0 1338840 0 693653080 99 function
<653 more rows. Type e.g. '_.more' to view.>
可以看到,dict 占用了大部分内存。然而这道这点儿当然不够,我还要知道“哪些字典”大,比如,哪个模块里创建的,怎么引用到它,之类问题。
难处就在于,这个情景下,嵌套的字典非常多,给一段代码模拟这个场景:
def rand():
return random.random()
def rand_int(i):
return random.randint(0, i)
def rdt(max_depth, max_width):
r = {}
if max_depth <= 1:
for i in range(rand_int(max_width)):
r[rand()] = rand()
else:
for i in range(rand_int(max_width)):
r[rand()] = rdt(rand_int(max_depth) - 1, max_width)
return r
t0 = rdt(9, 9)
t1 = rdt(7, 14)
t2 = rdt(5, 19)
t3 = rdt(3, 24)
现在,请问我直接创建的四个 t,哪个大?
“大”当然不是指那一个 PyObject 占用的空间大就行了,而是所有直接间接 referents dicts 都加在一起,才有意义。
所以类似这样的解答不行:
>>> (h0[0] - h0[0].referents).byvia
Partition of a set of 5 objects. Total size = 2168 bytes.
Index Count % Size % Cumulative % Referred Via:
0 1 20 1048 48 1048 48 "['t4']"
1 1 20 280 13 1328 61 "['t0']"
2 1 20 280 13 1608 74 "['t1']"
3 1 20 280 13 1888 87 "['t2']"
4 1 20 280 13 2168 100 "['t3']"
各位牛人,请教了
1
binfengxy 2017-08-02 16:43:43 +08:00
这个问题我只能参观了!
|
2
NoAnyLove 2017-08-02 23:03:32 +08:00
以前从来没有遇到过这种问题。提供一个思路,你需要 Pympler,每个变量创建前后调用 tracker.SummaryTracker,然后根据变化量就能知道内存占用了。
当然,更直观的方法就是 asizeof ``` >>> from pympler import asizeof >>> asizeof.asizeof(t0) 4880 ``` |
3
nthhdy OP 多谢 pympler 这个工具推荐
我搜 python memory profile and debug,为什么没搜出这个工具呢,只看到了 line profiler,heapy 啥的 这样搞是一个思路了,很笨的一个思路呵呵,很慢,跑十几分钟才跑出十分之一: ```python from pympler.asizeof import asizeof h0 = hp.heap() ds = h0[0] # 获取"根"dict set root_ds = (ds - ds.referrers).byid # 看一看每个“根 dict ”的 recursive size sizes = [] for i in range(len(root_ds)): info = i, asizeof(root_ds[i]) sizes.append(info) # check size ``` |