【发布时间】:2018-04-06 02:29:35
【问题描述】:
试试这样的代码:
import gc
import random
from concurrent.futures import ThreadPoolExecutor
zen = "Special cases aren't special enough to break the rules. "
def abc(length: int):
msg = ''.join(random.sample(zen, length))
print(msg)
del msg
if __name__ == '__main__':
pool = ThreadPoolExecutor(max_workers=8)
while True:
for x in range(256):
pool.submit(abc, random.randint(2, 6))
print('===================================================')
gc.collect()
如果代码在没有 ThreadPoolExecutor 的情况下运行,则可能需要大约 8MB,或者使用 str() 而不是 ''.join() 大约需要 30MB。但是这段代码一直在无限制地吃 RAM。我以为是random.sample或者别的什么原因造成的,结果证明是ThreadPoolExecutor中的''.join()导致了这个问题。
这让我很困惑,因为没有相互导入的模块(仅共享 zen),并且 del 或 Gc 都不起作用:(
ps:请注意,无限循环不是问题。当你运行类似的东西时:
while True:
print(1234567)
内存使用将保持在某一行以下(上面的代码可能不超过 1MB?)。顶部的代码没有递增的列表或字典,并且变量在模块末尾被 del 。所以当我认为线程完成时应该清理它,这显然不是。
pss:我们这样说:问题的原因是''.join()中的任何东西都不会被回收。就好像我们这样改变 abc 模块:
tmp = random.sample(zen, length)
msg = ''.join(tmp)
print(msg[:8])
del msg, tmp
Gc 工作效率高,使用量保持在 26MB 左右。
那么我在使用 ''.join() 时是否遗漏了什么或者 python 语言存在错误?
【问题讨论】:
-
但是这里有一个无限循环。你的程序永远不会结束。由于您没有得到
submit的结果,因此池会越来越大。 -
你的 while 循环永远不会中断。显然,它将继续增长。
-
抱歉没有说清楚。当您使用单线程或没有''.join() 运行时,即使使用无限循环,内存使用量也会保持在某一行以下,例如8MB 或更多。它不会不会(重要声明 3 次)增长到数百 MB 甚至更多(4096 个线程的类似示例会占用 13GB RAM)。只有'循环让它成长对我来说没有意义兄弟。
标签: python multithreading memory-leaks