为什么我的Python循环要消耗所有内存?

为什么我的Python循环要消耗所有内存?,python,Python,我想在一定时间内生成并保存一组元组。然而,我发现如果有足够的时间,这个程序似乎会消耗掉所有的内存 我试过两种方法。一个是删除新生成的变量,另一个是gc.collect()。但他们两人都没有成功。如果我只是生成而不保留元组,程序将消耗有限的内存 生成并保持:gk.py import gc import time from memory_profiler import profile from random import sample from sys import getsizeof @pro

我想在一定时间内生成并保存一组元组。然而,我发现如果有足够的时间,这个程序似乎会消耗掉所有的内存

我试过两种方法。一个是删除新生成的变量,另一个是gc.collect()。但他们两人都没有成功。如果我只是生成而不保留元组,程序将消耗有限的内存

生成并保持:gk.py

import gc
import time
from memory_profiler import profile
from random import sample
from sys import getsizeof


@profile
def loop(limit):
    t = time.time()
    i = 0
    A = set()
    while True:
        i += 1
        duration = time.time() - t
        a = tuple(sorted(sample(range(200), 100)))
        A.add(a)
        if not i % int(1e4):
            print('step {:.2e}...'.format(i))
        if duration > limit:
            print('done')
            break
        # method 1: delete the variables
#        del duration, a
        # method 2: use gc
#        gc.collect()
    memory = getsizeof(t) + getsizeof(i) + getsizeof(duration) + \
             getsizeof(a) + getsizeof(limit) + getsizeof(A)
    print('memory consumed: {:.2e}MB'.format(memory/2**20))
    pass


def main():
    limit = 300
    loop(limit)
    pass


if __name__ == '__main__':
    print('running...')
    main()
生成并不保留:gnk.py

import time
from memory_profiler import profile
from random import sample
from sys import getsizeof


@profile
def loop(limit):
    t = time.time()
    i = 0
    while True:
        i += 1
        duration = time.time() - t
        a = tuple(sorted(sample(range(200), 100)))
        if not i % int(1e4):
            print('step {:.2e}...'.format(i))
        if duration > limit:
            print('done')
            break
    memory = getsizeof(t) + getsizeof(i) + getsizeof(duration) + \
             getsizeof(a) + getsizeof(limit)
    print('memory consumed: {:.2e}MB'.format(memory/2**20))
    pass


def main():
    limit = 300
    loop(limit)
    pass


if __name__ == '__main__':
    print('running...')
    main()
在cmd/shell中使用“mprof”(需要模块内存\u分析器)检查内存使用情况

mprof run my_file.py
mprof plot
gk.py的结果

memory consumed: 4.00e+00MB
Filename: gk.py

Line #    Mem usage    Increment   Line Contents
================================================
    12     32.9 MiB     32.9 MiB   @profile
    13                             def loop(limit):
    14     32.9 MiB      0.0 MiB       t = time.time()
    15     32.9 MiB      0.0 MiB       i = 0
    16     32.9 MiB      0.0 MiB       A = set()
    17     32.9 MiB      0.0 MiB       while True:
    18    115.8 MiB      0.0 MiB           i += 1
    19    115.8 MiB      0.0 MiB           duration = time.time() - t
    20    115.8 MiB      0.3 MiB           a = tuple(sorted(sample(range(200), 100)))
    21    115.8 MiB      2.0 MiB           A.add(a)
    22    115.8 MiB      0.0 MiB           if not i % int(1e4):
    23    111.8 MiB      0.0 MiB               print('step {:.2e}...'.format(i))
    24    115.8 MiB      0.0 MiB           if duration > limit:
    25    115.8 MiB      0.0 MiB               print('done')
    26    115.8 MiB      0.0 MiB               break
    27                                     # method 1: delete the variables
    28                             #        del duration, a
    29                                     # method 2: use gc
    30                             #        gc.collect()
    31                                 memory = getsizeof(t) + getsizeof(i) + getsizeof(duration) + \
    32    115.8 MiB      0.0 MiB                getsizeof(a) + getsizeof(limit) + getsizeof(A)
    33    115.8 MiB      0.0 MiB       print('memory consumed: {:.2e}MB'.format(memory/2**20))
    34    115.8 MiB      0.0 MiB       pass
gnk.py的结果

memory consumed: 9.08e-04MB
Filename: gnk.py

Line #    Mem usage    Increment   Line Contents
================================================
    11     33.0 MiB     33.0 MiB   @profile
    12                             def loop(limit):
    13     33.0 MiB      0.0 MiB       t = time.time()
    14     33.0 MiB      0.0 MiB       i = 0
    15     33.0 MiB      0.0 MiB       while True:
    16     33.0 MiB      0.0 MiB           i += 1
    17     33.0 MiB      0.0 MiB           duration = time.time() - t
    18     33.0 MiB      0.1 MiB           a = tuple(sorted(sample(range(200), 100)))
    19     33.0 MiB      0.0 MiB           if not i % int(1e4):
    20     33.0 MiB      0.0 MiB               print('step {:.2e}...'.format(i))
    21     33.0 MiB      0.0 MiB           if duration > limit:
    22     33.0 MiB      0.0 MiB               print('done')
    23     33.0 MiB      0.0 MiB               break
    24                                 memory = getsizeof(t) + getsizeof(i) + getsizeof(duration) + \
    25     33.0 MiB      0.0 MiB                getsizeof(a) + getsizeof(limit)
    26     33.0 MiB      0.0 MiB       print('memory consumed: {:.2e}MB'.format(memory/2**20))
    27     33.0 MiB      0.0 MiB       pass
我有两个问题:

  • 这两个程序消耗的内存都比所占用的变量多。“gk.py”消耗了115.8MB,其变量占4.00MB。“gnk.py”消耗了33.0MB,其变量占用了9.08e-04MB。为什么程序消耗的内存比相应变量占用的内存多

  • “gk.py”消耗的内存随时间线性增加。“gnk.py”消耗的内存会随着时间的推移而不断保留。为什么会发生这种情况


  • 如果有任何帮助,我们将不胜感激。

    鉴于集合的大小不断增加,它最终将消耗所有内存

    估计值(从我的计算机):


    查看python
    generator
    。你在用这些元组做什么?对
    a=tuple(排序(样本(范围(200),100))
    不做任何操作。你只需这样做,然后忽略结果。我想生成并保留元组。“gk.py”(generate&keep)是当前的文件,“gnk.py”(generate¬keep)用于比较。当然,您正在消耗越来越多的内存。存储的元组越来越多。期望不消耗你所有的记忆最终表明你对记忆消耗的含义有一个糟糕的心理模型。正如@user2357112所说的,我不知道你想要什么。您正在生成元组并存储它们。你希望他们不带走记忆吗?你不是把它“保存在文件中”,而是把它保存在内存中。如果要将其保存在文件中,则需要将其写入文件。为什么在无限循环的内存中需要一堆随机元组?我已经编辑了我的问题。这次你能给点建议吗?对于问题2,你觉得什么奇怪?“gk.py”内存消耗会随着时间的推移而增加,或者“gnk.py”内存消耗不会增加,这一事实不要紧。我现在明白了。似乎集合“A”是动态分配内存的。这就是记忆增加的原因。
    10 seconds of code running ~ 5e4 tuples saved to the set
    300 seconds of code running ~ 1.5e6 tuples saved to the set
    
    1 tuple = 100 integers ~ 400bytes
    
    total:
    
    1.5e6 * 400bytes = 6e8bytes = 600MB filled in 300s