python - ThreadPoolExecutor 中的 ''.join() 占用内存

标签 python multithreading memory-leaks

试试这样的代码:

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/

相关文章:

c++ - 有什么方法可以知道线程使用了多少内存?

Android调试C内存泄漏

python - 为什么我看不到 mod_wsgi 的进程

python - 添加一个颜色条,其颜色对应于现有图中的不同线条

ruby-on-rails - 如何在使用 activerecords 和多线程时管理打开和关闭数据库连接

c - 即使没有内存泄漏,Valgrind 也会出现无效读取错误

linux -/proc/$pid/maps 显示在 x86_64 linux 上没有 rwx 权限的页面

c# - 创建一个 Python COM 对象

没有 PANDAS 的 Python 聚合

multithreading - Delphi 位图中的异步线程绘制