Python Garbage Collection: Memory no longer needed not released to OS?
我已经用烧瓶编写了一个应用程序,并将芹菜用于一个长期运行的任务。当负载测试时,我注意到芹菜任务即使在完成任务之后也不会释放内存。所以我在谷歌上找到了这个小组讨论……
https://groups.google.com/forum/!主题/芹菜用户/jvc3ki3ktlw
在讨论中,它说,这就是Python的工作原理。
另一篇文章在https://hbfs.wordpress.com/2013/01/08/python-memory-management-part-ii/上说
"但是从操作系统的角度来看,程序的大小是分配给python的总(最大)内存。由于python只在Windows上将内存返回到堆上的操作系统(分配除小对象以外的其他对象),因此如果在Linux上运行,则只能看到程序使用的总内存增加。"
我使用Linux。所以我写了下面的脚本来验证它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import gc def memory_usage_psutil(): # return the memory usage in MB import resource print 'Memory usage: %s (MB)' % (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000.0) def fileopen(fname): memory_usage_psutil()# 10 MB f = open(fname) memory_usage_psutil()# 10 MB content = f.read() memory_usage_psutil()# 14 MB def fun(fname): memory_usage_psutil() # 10 MB fileopen(fname) gc.collect() memory_usage_psutil() # 14 MB import sys from time import sleep if __name__ == '__main__': fun(sys.argv[1]) for _ in range(60): gc.collect() memory_usage_psutil()#14 MB ... sleep(1) |
输入是一个4MB文件。即使在从"fileopen"函数返回后,4MB内存也没有释放。当循环运行时,我检查了htop输出,常驻内存保持在14MB。因此,除非进程停止,否则内存将一直保留。
因此,如果芹菜工人在完成任务后没有被杀死,它将为自己保留记忆。我知道我可以使用max-tasks-per-child-config值来终止进程并生成一个新的进程。有没有其他方法可以将内存从Python进程返回到操作系统?.
我觉得你的测量方法和解释有点离谱。您使用的是
这也可能意味着进程释放了4mib,但操作系统没有回收内存,因为如果进程已经映射了内存,那么分配新的4mib会更快。为了使它更加复杂,程序可以并且确实使用"空闲列表",即不在活动使用中但未释放的内存块的列表。这也是使未来分配更快的常见技巧。
我写了一个简短的脚本来演示虚拟内存使用量和max rss之间的区别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import numpy as np import psutil import resource def print_mem(): print("----------") print("ru_maxrss: {:.2f}MiB".format( resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024)) print("virtual_memory.used: {:.2f}MiB".format( psutil.virtual_memory().used / 1024 ** 2)) print_mem() print("allocating large array (80e6,)...") a = np.random.random(int(80e6)) print_mem() print("del a") del a print_mem() print("read testdata.bin (~400MiB)") with open('testdata.bin', 'rb') as f: data = f.read() print_mem() print("del data") del data print_mem() |
结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ---------- ru_maxrss: 22.89MiB virtual_memory.used: 8125.66MiB allocating large array (80e6,)... ---------- ru_maxrss: 633.20MiB virtual_memory.used: 8731.85MiB del a ---------- ru_maxrss: 633.20MiB virtual_memory.used: 8121.66MiB read testdata.bin (~400MiB) ---------- ru_maxrss: 633.20MiB virtual_memory.used: 8513.11MiB del data ---------- ru_maxrss: 633.20MiB virtual_memory.used: 8123.22MiB |
号
很明显,
关于
used: memory used, calculated differently depending on the platform and designed for informational purposes only.
号