zl程序教程

您现在的位置是:首页 >  后端

当前栏目

《Python高性能编程》——2.10 用heapy调查堆上的对象

2023-09-11 14:17:44 时间

本节书摘来自异步社区《Python高性能编程》一书中的第2章,第2.10节,作者[美] 戈雷利克 (Micha Gorelick),胡世杰,徐旭彬 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.10 用heapy调查堆上的对象

Guppy项目有一个内存堆的调查工具叫作heapy,可以让你查看Python堆中对象的数量以及每个对象的大小。当你需要知道某一时刻有多少对象被使用以及它们是否被垃圾收集时,你尤其需要这种深入解释器内部去了解内存中实际内容的能力。如果你受困于内存泄漏(可能由于你的对象的引用隐藏于一个复杂系统中),那么这个工具能帮你找到问题的关键点。

当你在审查你的代码,看它是否如你预期那样生成对象时,你会发现这个工具非常有用——结果很可能令你吃惊,并为你带来新的优化方向。

为了使用heapy,你需要用命令pip install guppy安装guppy包。

例2-12的代码是Julia代码的一个略有修改的版本。calc_pure_python使用了堆对象hpy,我们在三个地方打印堆的内容。

例2-12 用heapy查看代码运行时对象数量的变化

def calc_pure_python(draw_output, desired_width, max_iterations):

 while xcoord x2:

 x.append(xcoord)

 xcoord += x_step

 from guppy import hpy; hp = hpy()

 print "heapy after creating y and x lists of floats"

 h = hp.heap()

 print h

 print

 zs = []

 cs = []

 for ycoord in y:

 for xcoord in x:

 zs.append(complex(xcoord, ycoord))

 cs.append(complex(c_real, c_imag))

 print "heapy after creating zs and cs using complex numbers"

 h = hp.heap()

 print h

 print

 print "Length of x:", len(x)

 print "Total elements:", len(zs)

 start_time = time.time()

 output = calculate_z_serial_purepython(max_iterations, zs, cs)

 end_time = time.time()

 secs = end_time - start_time

 print calculate_z_serial_purepython.func_name + " took", secs, "seconds"

 print

 print "heapy after calling calculate_z_serial_purepython"

 h = hp.heap()

 print h

 print

例2-13的输出显示了内存的使用在创建zs和cs列表后变得有趣:它增长了大约80MB,因为2000000个复数对象消耗了64000000字节。这些复数对象占据了目前使用的大多数内存。如果你想要优化这个程序的内存用量,这个结果可用于揭示目前保存的对象数量以及它们总共占用的空间。

例2-13 heapy输出显示了我们代码执行时每一个主要阶段的对象总数

$ python julia1_guppy.py

heapy after creating y and x lists of floats

Partition of a set of 27293 objects. Total size = 3416032 bytes.

 Index Count % Size % Cumulative % Kind (class / dict of class)

 0 10960 40 1050376 31 1050376 31 str

 1 5768 21 465016 14 1515392 44 tuple

 2 199 1 210856 6 1726248 51 dict of type

 3 72 0 206784 6 1933032 57 dict of module

 4 1592 6 203776 6 2136808 63 types.CodeType

 5 313 1 201304 6 2338112 68 dict (no owner)

 6 1557 6 186840 5 2524952 74 function

 7 199 1 177008 5 2701960 79 type

 8 124 0 135328 4 2837288 83 dict of class

 9 1045 4 83600 2 2920888 86 __builtin__.wrapper_descriptor

 91 more rows. Type e.g. _.more to view. 

heapy after creating zs and cs using complex numbers

Partition of a set of 2027301 objects. Total size = 83671256 bytes.

 Index Count % Size % Cumulative % Kind (class / dict of class)

 0 2000000 99 6400000 76 64000000 76 complex

 1 185 0 16295368 19 80295368 96 list

 2 10962 1 1050504 1 81345872 97 str

 3 5767 0 464952 1 81810824 98 tuple

 4 199 0 210856 0 82021680 98 dict of type

 5 72 0 206784 0 82228464 98 dict of module

 6 1592 0 203776 0 82432240 99 types.CodeType

 7 319 0 202984 0 82635224 99 dict (no owner)

 8 1556 0 186720 0 82821944 99 function

 9 199 0 177008 0 82998952 99 type

 92 more rows. Type e.g. _.more to view. 

Length of x: 1000

Total elements: 1000000

calculate_z_serial_purepython took 13.2436609268 seconds

heapy after calling calculate_z_serial_purepython

Partition of a set of 2127696 objects. Total size = 94207376 bytes.

 Index Count % Size % Cumulative % Kind (class / dict of class)

 0 2000000 94 64000000 68 64000000 68 complex

 1 186 0 24421904 26 88421904 94 list

 2 100965 5 2423160 3 90845064 96 int

 3 10962 1 1050504 1 91895568 98 str

 4 5767 0 464952 0 92360520 98 tuple

 5 199 0 210856 0 92571376 98 dict of type

 6 72 0 206784 0 92778160 98 dict of module

 7 1592 0 203776 0 92981936 99 types.CodeType

 8 319 0 202984 0 93184920 99 dict (no owner)

 9 1556 0 186720 0 93371640 99 function

 92 more rows. Type e.g. _.more to view. 

第三段显示了在计算完Julia集合后,我们占用了94MB的内存。除了之前的复数,我们现在还保存了大量的整数,列表中的项目也变多了。

hpy.setrelheap()可以用来创建一个内存断点,当后续调用hpy.heap()时就会产生一个跟这个断点的差额。这样你就可以略过断点前由Python内部操作导致的内存分配。


Python函数是所谓的第一类对象(First-Class Object)是什么鬼? 之前写过一篇关于装饰器的文章,虽然写得还算不错,但是也有不少同学表示没看懂,我大概分析了其中的原因,主要问题是他们不理解函数,因为Python中的函数不同于其它语言。
【python可视化】python编码规范、标准库与扩展库对象的导入与使用 代码布局和排版在很大程度上决定了代码可读性的好坏,变量名、函数名、类名等标识符名称也会对代码的可读性带来一定的影响。一个好的python代码不仅应该是正确的,还应该是漂亮的、优雅的。
异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。