来自concurrent.futures的RSS内存使用情况

我有一个简单的脚本,试图强调concurrent.futures库如下:

#! /usr/bin/python import psutil import gc import os from concurrent.futures import ThreadPoolExecutor WORKERS=2**10 def run(): def x(y): pass with ThreadPoolExecutor(max_workers=WORKERS) as pool: for _ in pool.map(x, [i for i in range(WORKERS)]): pass if __name__ == '__main__': print('%d objects' % len(gc.get_objects())) print('RSS: %s kB' % (psutil.Process(os.getpid()).get_memory_info().rss / 2**10)) run() print('%d objects' % len(gc.get_objects())) print('RSS: %s kB' % (psutil.Process(os.getpid()).get_memory_info().rss / 2**10)) 

最后在运行python 2.7的2核linux机器上生成以下输出:

 # time ./test.py 7048 objects RSS: 11968 kB 6749 objects RSS: 23256 kB real 0m1.077s user 0m0.875s sys 0m0.316s 

虽然这是一个有点人为的例子,但我很难理解RSS在这种情况下增加的原因以及分配内存的用途。

Linux应该使用COW来处理分叉的内存,但是由于CPython是引用计数的,因此需要更新引用,所以inheritance内存的部分不会是真正的只读。 考虑到引用计数开销最小,12MB的增长对我来说是令人惊讶的。 如果不是使用ThreadPoolExecutor ,而是使用threading库产生守护进程线程,则RSS将只增加4MB。

我当然不清楚是否怀疑CPython分配器还是glibc分配器,但是我的理解是后者应该可以处理这种并发的风格,并且能够在衍生的线程中重新使用舞台进行分配。

我使用python 2.7.9下的concurrent.futures 3.0.3的backported版本,在4.1内核上使用glibc 2.4。 任何意见或提示如何进一步调查将不胜感激。

大多数内存分配器不会将所有的内存返回给操作系统。

尝试两次调用run()并在第二次之前/之后检查RSS。

(也就是说,可笑的线程数通常不是一个好主意)

我建议你阅读从https://stackoverflow.com/a/1718522/5632150这个答复

正如他所说,你可以产生的线程的数量取决于你的线程做或不做任何I / O操作的事实。 如果有的话,有一些方法来优化这个问题。 如果不是,我通常做MAX_THREADS = N_CORES + 1。

不知道,但是,你想在一个核心上产生1024线程?