我最近遇到了关于python内存分配的this article。
在这个页面中,它描述了python的内存使用情况,并且在那里有一个显示整数列表的深度复制的示例。我自己在Python 2.7上做了基准测试
Line # Mem usage Increment Line Contents
================================================
4 28.051 MiB 0.000 MiB @profile
5 def function():
6 59.098 MiB 31.047 MiB x = list(range(1000000)) # allocate a big list
7 107.273 MiB 48.176 MiB y = copy.deepcopy(x)
8 99.641 MiB -7.633 MiB del x
9 99.641 MiB 0.000 MiB return y
所以直接删除x只删除x和所有对整数的引用到x吗?
这样做也无济于事(那么del x和del x [:]有什么区别?):
Line # Mem usage Increment Line Contents
================================================
4 28.047 MiB 0.000 MiB @profile
5 def function():
6 59.094 MiB 31.047 MiB x = list(range(1000000)) # allocate a big list
7 107.270 MiB 48.176 MiB y = copy.deepcopy(x)
8 99.637 MiB -7.633 MiB del x[:]
9 99.637 MiB 0.000 MiB return y
与深度复制相反,如果我使用复制,删除后似乎内存恢复到新创建x时的先前状态
Line # Mem usage Increment Line Contents
================================================
4 28.039 MiB 0.000 MiB @profile
5 def function():
6 59.090 MiB 31.051 MiB x = list(range(1000000)) # allocate a big list
7 66.895 MiB 7.805 MiB y = copy.copy(x)
8 59.262 MiB -7.633 MiB del x[:]
9 59.262 MiB 0.000 MiB return y
对于dict:
Line # Mem usage Increment Line Contents
================================================
4 28.051 MiB 0.000 MiB @profile
5 def function():
6 100.523 MiB 72.473 MiB x = dict((e, e) for e in xrange(1000000))
7 183.398 MiB 82.875 MiB y = copy.deepcopy(x)
8 135.395 MiB -48.004 MiB del x
9 135.395 MiB 0.000 MiB return y
对于列表列表(与整数列表比较,我假设del x或del x [:]只删除堆上那个庞大的数组列表?):
Line # Mem usage Increment Line Contents
================================================
4 28.043 MiB 0.000 MiB @profile
5 def function():
6 107.691 MiB 79.648 MiB x = [[] for _ in xrange(1000000)]
7 222.312 MiB 114.621 MiB y = copy.deepcopy(x)
8 214.680 MiB -7.633 MiB del x[:]
9 214.680 MiB 0.000 MiB return y
所以我想问:
在这个例子中,我如何或者如何在x中释放所有下划线列表?
Line # Mem usage Increment Line Contents
================================================
4 28.047 MiB 0.000 MiB @profile
5 def function():
6 248.008 MiB 219.961 MiB x = [list(range(10)) for _ in xrange(1000000)]
7 502.195 MiB 254.188 MiB y = copy.deepcopy(x)
8 494.562 MiB -7.633 MiB del x[:]
9 494.562 MiB 0.000 MiB return y
答案 0 :(得分:0)
del
不像C中那样释放变量,只是说你不再需要它。然后发生的是实现细节。
所以这里发生的事情是del
不空闲内存,它只是告诉python你完成了变量。具体做法是:
7.5。 del声明
del_stmt :: =“del”target_list
删除的递归定义非常类似于定义赋值的方式。这里有一些提示,而不是详细说明。
删除目标列表会从左到右递归删除每个目标。
删除名称将删除该名称与本地或全局名称空间的绑定,具体取决于名称是否出现在同一代码块中的全局语句中。如果名称未绑定,则将引发NameError异常。
删除属性引用,订阅和切片将传递给所涉及的主对象;删除切片通常等同于分配正确类型的空切片(但即使这是由切片对象确定的)。
请注意,没有提及释放内存。相反的是,你告诉python它可以做什么"无论它想要什么"带着那段记忆。在这种情况下,你的python实现(我假设是CPython)存储内存以供以后在内存缓存中使用。这允许python通过以后不需要分配更多内存来更快地运行。
考虑这个示例,我们del x
,然后再次创建y
的副本。请注意,第二次复制期间分配的内存量小于第一次复制期间分配的内存量。这是因为重用了内存。如果我们再次这样做,我们会发现在第三个副本中几乎没有任何内存被分配,因为python只是重新使用以前分配的内存:
Line # Mem usage Increment Line Contents
================================================
4 34.777 MiB 0.000 MiB @profile
5 def function():
6 37.504 MiB 2.727 MiB x = [list(range(10)) for _ in xrange(10000)]
7 40.773 MiB 3.270 MiB y = copy.deepcopy(x)
8 40.773 MiB 0.000 MiB del x
9 41.820 MiB 1.047 MiB y2 = copy.deepcopy(y)
10 41.820 MiB 0.000 MiB del y2
11 41.824 MiB 0.004 MiB y3 = copy.deepcopy(y)
12 41.824 MiB 0.000 MiB return y
优秀"博客":http://www.evanjones.ca/memoryallocator/
http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm