是什么在占用这个forloop的内存?

2024-10-02 06:28:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我在玩memory_profiler包(从pip下载),更具体地说,通过先创建一个临时列表和循环遍历“迭代器列表”来观察循环遍历列表的内存效率。在

这是我不久前遇到的一个问题,我想对我的解决方案进行基准测试。问题是我需要将一个列表中的每个元素与同一个列表中的下一个元素进行比较,直到所有元素都被“处理”。所以我想这应该是一个O(n^2)的解决方案(如果选择了最朴素的解决方案,对于list中的每个元素,循环遍历list)。在

不管怎样,下面的三个函数都在做相同的事情(或多或少);在一个压缩后的列表上循环,这个列表本身偏移了一个。在

import cProfile

@profile
def zips():
    li = range(1,20000000)
    for tup in zip(li,li[1:]):
        pass
    del li

@profile
def izips():
    from itertools import izip
    li = range(1,20000000)
    for tup in izip(li,li[1:]):
        pass
    del li

@profile
def izips2():
    from itertools import izip
    li = range(1,20000000)
    for tup in izip(li,li[1:]):
        del tup
    del li



if __name__ == '__main__':
    zips()
    # izips()
    # izips2()

令我惊讶的是内存使用情况,首先我运行了zips()函数,虽然我认为我确实清理了,但最终还是有大约1.5 GB的内存:

^{pr2}$

然后关闭解释器实例并重新打开它以运行下一个测试,即izips()函数:

ipython -m memory_profiler python_profiling.py 
Filename: python_profiling.py

Line #    Mem usage    Increment   Line Contents
================================================
    17                             @profile
    18    27.449 MB     0.000 MB   def izips():
    19    27.449 MB     0.000 MB    from itertools import izip
    20   649.051 MB   621.602 MB    li = range(1,20000000)
    21  1899.512 MB  1250.461 MB    for tup in izip(li,li[1:]):
    22  1746.922 MB  -152.590 MB        pass
    23  1594.332 MB  -152.590 MB    del li

最后,我运行了一个测试(在重新启动解释器之后),我尝试显式地删除for循环中的元组,以确保它的内存能够被释放(也许我没有正确地思考这个问题?)。结果没什么不同,所以我猜要么我没有提示GC,要么这不是我内存开销的来源。在

ipython -m memory_profiler python_profiling.py 
Filename: python_profiling.py

Line #    Mem usage    Increment   Line Contents
================================================
    25                             @profile
    26    20.109 MB     0.000 MB   def izips2():
    27    20.109 MB     0.000 MB    from itertools import izip
    28   641.676 MB   621.566 MB    li = range(1,20000000)
    29  1816.953 MB  1175.277 MB    for tup in izip(li,li[1:]):
    30  1664.387 MB  -152.566 MB        del tup
    31  1511.797 MB  -152.590 MB    del li

底线: 我认为for循环本身的开销是最小的,因此,我期望略高于~620.000MB(存储列表所需的内存),但是看起来我的内存中有大约2个大小为20.000.000的列表+更多的开销。有人能帮我解释一下这些记忆是用来做什么的吗??(每次运行结束时,是什么占用了大约1.5 GB的空间?)在


Tags: 内存inimport元素列表fordefrange
1条回答
网友
1楼 · 发布于 2024-10-02 06:28:37

请注意,操作系统将内存分块分配,并不一定一次性回收所有内存。我发现内存分析包非常不准确,因为它似乎没有考虑到这一点。在

您的li[1:]片创建了一个包含(2*10**7)-1元素的列表,几乎是一个全新的副本,可以轻松地将列表所需的内存空间加倍。zip()调用还返回一个全新的list对象,即压缩操作的输出,同样需要内存来存储中间结果,外加2000万个2元元组。在

可以使用新的迭代器代替切片:

def zips():
    from itertools import izip
    li = range(1,20000000)
    next_li = iter(li)
    next(next_li)  # advance one step
    for tup in izip(li, next_li):
        pass
    del li

iter()调用返回的列表迭代器要轻得多;它只保留对原始列表和指针的引用。将其与izip()结合使用可以避免创建输出列表。在

相关问题 更多 >

    热门问题