首先,我想测试生成器和列表理解之间的内存使用情况。本书给了我一个小小的代码片段,我在我的PC上运行它(python3.6,Windows),找到意想不到的东西。
FOllowing是我的代码,它不满足以前的意见(在sum函数中)。
import tracemalloc
from time import time
def timeIt(func):
start = time()
func()
print('%s use time' % func.__name__, time() - start)
return func
tracemalloc.start()
numbers = range(1, 1000000)
@timeIt
def lStyle():
return sum([i for i in numbers if i % 3 == 0])
@timeIt
def gStyle():
return sum((i for i in numbers if i % 3 == 0))
lStyle()
gStyle()
shouldSize = [i for i in numbers if i % 3 == 0]
snapshotL = tracemalloc.take_snapshot()
top_stats = snapshotL.statistics('lineno')
print("[ Top 10 ]")
for stat in top_stats[:10]:
print(stat)
输出:
lStyle use time 0.4460000991821289
gStyle use time 0.6190001964569092
[ Top 10 ]
F:/py3proj/play.py:31: size=11.5 MiB, count=333250, average=36 B
F:/py3proj/play.py:33: size=448 B, count=1, average=448 B
F:/py3proj/play.py:22: size=136 B, count=1, average=136 B
F:/py3proj/play.py:17: size=136 B, count=1, average=136 B
F:/py3proj/play.py:14: size=76 B, count=2, average=38 B
F:/py3proj/play.py:8: size=34 B, count=1, average=34 B
两点:
我想也许sum函数做了我不知道的事情。谁能解释一下?
这本书是High Perfoamance Python.chapter 5.但是我确实与本书不同,以检查其他背景下的有效性。他的代码在book_code,他并没有将列表理解放在总和函数中。
答案 0 :(得分:2)
在时间性能测试方面,我确实依赖于timeit
模块,因为它会自动执行多次代码运行。
在我的系统上,timeit给出了以下结果(由于大量运行,我大大减小了尺寸):
>>> timeit.timeit("sum([i for i in numbers if i % 3 == 0])", "numbers = range(1, 1000)")
59.54427594248068
>>> timeit.timeit("sum((i for i in numbers if i % 3 == 0))", "numbers = range(1, 1000)")
64.36398425334801
所以发电机慢了大约8%(*)。这实际上并不令人惊讶,因为生成器必须执行一些代码动态以获取下一个值,而预先计算的列表只增加其当前指针。
记忆评估恕我直言更复杂,所以我使用了来自activestate的Compute Memory footprint of an object and its contents (Python recipe)
>>> numbers = range(1, 100)
>>> numbers = range(1, 100000)
>>> l = [i for i in numbers if i % 3 == 0]
>>> g = (i for i in numbers if i % 3 == 0)
>>> total_size(l)
1218708
>>> total_size(g)
88
>>> total_size(numbers)
48
我的解释是列表使用内存来处理所有项目(这不是一个惊喜),而生成器只需要很少的值和一些代码,因此生成器的内存占用量要小得多。
我强烈认为您已将tracemalloc
用于不适用的内容。它的目的是搜索可能的内存泄漏(大块内存从未解除分配),而不是控制单个对象使用的内存。
请注意:我只能测试小尺寸。但是对于非常大的大小,列表可能耗尽可用内存,并且机器将使用来自交换的虚拟内存。在这种情况下,列表版本将变得更慢。更多详情there