gpt4 book ai didi

python - 理解python内存分配和释放

转载 作者:太空狗 更新时间:2023-10-30 01:36:42 25 4
gpt4 key购买 nike

我最近遇到了 this article关于 python 内存分配。

在此页面中,它描述了 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

与deepcopy相比,如果我使用copy,删除后似乎内存恢复到新创建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

对于听写:

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

所以我想问:

  1. 那么如果没有办法收回那些被整数占用的内存呢?整数也是一个对象,对吧?为什么内 stub 本没有被释放?不能只声明整数?还是 float 和 string 也一样?对象引用也是如此?
  2. 为什么有 -7 MB 的内存?是不是因为实现为数组列表的列表从堆中释放了?
  3. 不管是list还是dict,del x只能free数据结构本身(我的意思是数组list结构,或者dict结构),但是整型,对象引用可以标记为free,不能返回系统?

在这个例子中,我该如何或者是否有办法释放 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

最佳答案

长话短说

del 不像 C 中那样释放变量,它只是表示您不再需要它。然后发生的是实现细节。

理由

所以这里发生的是 del 释放内存,它只是告诉 python 您已完成对变量的处理。具体来说:

7.5. The del statement

del_stmt ::= “del” target_list

Deletion is recursively defined very similar to the way assignment is defined. Rather than spelling it out in full details, here are some hints.

Deletion of a target list recursively deletes each target, from left to right.

Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a global statement in the same code block. If the name is unbound, a NameError exception will be raised.

Deletion of attribute references, subscriptions and slicings is passed to the primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object).

请注意,这里没有提到释放内存。相反发生的是你告诉 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

关于python - 理解python内存分配和释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45687704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com