堆上分配的内存可能会出现高水位标记。
Python PyObject_Malloc在4个KiB池中分配小对象()的内部优化使情况复杂化,分类为8字节倍数的分配大小-最多256字节(3.3中为512字节)。池本身位于256 KiB竞技场中,因此,如果仅在一个池中使用一个块,则不会释放整个256 KiB竞技场。在Python 3.3中,小型对象分配器已切换为使用匿名内存映射而不是堆,因此它在释放内存方面应表现更好。
此外,内置类型维护以前分配的对象的空闲列表,这些对象可能使用也可能不使用小对象分配器。该
int类型维护一个具有自己分配的内存的空闲列表,要清除它,需要调用
PyInt_ClearFreeList()。可以通过做一个full来间接地调用它
gc.collect。
这样尝试,然后告诉我你得到了什么。这是
psutil.Process.memory_info的链接。
import osimport gcimport psutilproc = psutil.Process(os.getpid())gc.collect()mem0 = proc.get_memory_info().rss# create approx. 10**7 int objects and pointersfoo = ['abc' for x in range(10**7)]mem1 = proc.get_memory_info().rss# unreference, including x == 9999999del foo, xmem2 = proc.get_memory_info().rss# collect() calls PyInt_ClearFreeList()# or use ctypes: pythonapi.PyInt_ClearFreeList()gc.collect()mem3 = proc.get_memory_info().rsspd = lambda x2, x1: 100.0 * (x2 - x1) / mem0print "Allocation: %0.2f%%" % pd(mem1, mem0)print "Unreference: %0.2f%%" % pd(mem2, mem1)print "Collect: %0.2f%%" % pd(mem3, mem2)print "Overall: %0.2f%%" % pd(mem3, mem0)
输出:
Allocation: 3034.36%Unreference: -752.39%Collect: -2279.74%Overall: 2.23%
编辑:
我改用相对于进程VM大小的度量来消除系统中其他进程的影响。
当顶部的连续可用空间达到恒定,动态或可配置的阈值时,C运行时(例如
glibc,msvcrt)会缩小堆。使用
glibc,你可以使用
mallopt(M_TRIM_THRESHOLD)进行调整。鉴于此,如果堆的收缩量比你的块减少的量更大,甚至更多,也就不足为奇了free。
在
3.x range中不会创建列表,因此上面的测试不会创建1000万个int对象。即使这样做,int3.x中的类型也基本上是
2.x long,它没有实现自由列表。



