试试这样的代码:
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。但是这段代码一直在无限制地吃内存。我以为是random.sample什么的导致的,结果证明是ThreadPoolExecutor中的''.join()导致了这个问题。
这让我感到困惑,因为没有模块相互导入(仅共享 zen),而且 del 或 Gc 都不起作用 :(
ps:请注意无限循环不是问题。当你运行类似的东西时:
while True:
print(1234567)
内存使用会保持在某一行以下(上面的代码可能不会超过 1MB?)。顶部的代码没有递增列表或字典,并且变量已在模块末尾删除。所以它应该像我认为的那样在一个线程完成时被清理,这显然不是。
pss:这么说吧:问题的原因是''.join()中的任何东西都不会被回收。就好像我们这样更改 abc 模块:
tmp = random.sample(zen, length)
msg = ''.join(tmp)
print(msg[:8])
del msg, tmp
Gc 有效运行,使用量保持在 26MB 左右。
那么我在使用 ''.join() 时是否遗漏了什么或者 python 语言在那里有错误?
最佳答案
当您在没有线程的情况下运行代码时,每个句子都将完全执行,我的意思是 gc.collect()
将在内部循环结束后被调用。
但是当你用线程执行代码时,一个新线程会在最近一个线程结束之前被调用,所以新线程的数量会迅速增加,并且由于线程数量没有限制,你将拥有比您的 CPU 可以处理导致线程累积的问题。
关于python - ThreadPoolExecutor 中的 ''.join() 占用内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46924974/