Python内存管理机制详解:引用计数、垃圾回收与内存池
python如何进行内存管理
Python的内存管理主要有三种机制:引用计数机制;垃圾收集机制和内存池机制。Python引用计数机制简介引用计数用于确定对象在内存中拥有多少个引用。
即创建对象时;创建参考号。
不再需要该对象。
当这个对象的引用数达到0时,它收集垃圾。
特征1.当对象被赋予新名称或对象被添加到容器(列表、元组或字典)时。
增加对象的引用计数。
2.del用于在超出或重置对象或引用的范围时显式销毁该对象或引用。
对象的引用计数将减少。
3.可以使用sys.getrefcount()函数获取对象当前的引用计数。
在大多数情况下,参考系数比我们预期的要大得多。
对于可变数据(数字和字符串),解释器在程序的不同部分之间共享内存以节省内存。
垃圾收集机制的特点1.当有部分内存不再被使用时。
垃圾收集器会清理它们。
它反对检查参考号0并清除其内存空间。
当然,除了将引用计数清0之外;还有一个条件会被垃圾收集器清除:当两个对象互相引用时,它们的其他引用已经为0。
2、垃圾收集机制还有循环垃圾收集器,保证发出循环引用对象(a引用b,b引用a,其引用号绝不能为0)。
介绍Python中的内存池机制,多次使用的内存由较小的内存块级内存池组成。
这意味着Python在执行过程中会进行大量的malloc和free操作,频繁地在用户模式和核心模式之间切换会严重影响Python的执行效率。
为了加快Python的性能,Python引入了内存池机制来管理应用程序并释放小块内存。
内存池概念内存池的概念就是从内存池中预留内存到内存池作为第一需求。
新的内存将再次被使用。
这样做最明显的好处就是可以减少内存碎片,提高性能。
内存池的实现方式有很多种,其能力和应用范围也各不相同。
特点1.Python提供了内存的垃圾回收机制;但它将未使用的内存放入内存池中,而不是将其返回给操作系统。
2.皮马洛克定律。
为了加快Python的性能,Python引入了内存池机制来管理应用程序并释放小块内存。
3.Python中所有小于256字节的对象都使用pymalloc实现的分配器,较大的对象使用系统malloc。
4.整数,浮点数和列表等Python对象都有自己的私有内存池,并且它们的内存池在对象之间不共享。
也就是说,如果您分配多个整数。
用于缓存这些整数的内存未分配给浮点数。
python内存管理机制详解(gc模块)
1.Python内存管理机制Python中的内存管理包括一个私有堆(heap),其中包含所有Python对象和数据结构。该私有堆的管理由内部Python内存管理器确保。
Python内存管理器有多种组件来处理各种动态存储管理问题,例如共享、分区、预分配或缓存。
在最底层,原始内存分配器与操作系统的内存管理器交互,以确保私有堆中有足够的空间来存储所有与Python相关的数据。
在原始的内存分配器中,多个特定于对象的分配器在同一个堆上操作,并根据每个对象类型的特性实现不同的内存管理策略。
例如,整数对象在堆上的管理方式与字符串、元组或字典不同。
这是因为整数具有不同的存储要求以及速度和空间之间的不同权衡。
因此,Python内存管理器将一些工作分配给每个对象分配器,但确保后者在私有堆的范围内运行。
Python堆内存管理由解释器执行,不受用户控制。
避免小对象(<=512字节)的过多GC会带来性能损失。
Python使用子分配(内存池)来管理小对象的内存块。
对于大对象,使用标准C的分配器来分配内存。
Python的小对象分配器分为三个级别,从大到小:region、pool、block
Block是最小的级别。
每个块只能容纳固定大小的Python对象。
大小8~512字节,以8字节为增量分为64个不同类别
池是相同大小的块的集合。
通常池的大小为4kb,与虚拟内存页面的大小相匹配。
限制并修复池的块大小。
当当前Pool块中的对象被销毁时,可以通过Pool内存管理将新创建的对象插入到该块对象中。
相同大小的池通过双向链表(prevpool、nextpool字段)连接。
sidx用于标识块类型,arenaindex标识当前池所属的arena,ref.count标识池当前使用的块数,freeblock标识指向当前池中可用块的指针。
Freeblock实际上是作为单链表实现的。
如果某个块为空,则将其插入到freeblock链表的头部。
每个池都有三种状态:
已使用:部分使用。
full:full
empty:empty
usedpool为了高效的Pool管理,Python额外使用了Array和UsedPool来管理。
usedpool按顺序存储每个特征大小池的头指针,相同大小的池按照双向链表链接。
当分配新的内存空间时,创建一个特定大小的池并使用Usedpools来查找和探索头指针。
如果没有内存空间,只需在池双向链表的开头插入一个新池即可。
池和块都不是直接分配内存,而是使用arena分配的内存空间。
Arena是分配在堆上的256kb块。
在内存中,它提供了64个池。
所有arena也使用双向链表(prevarena、nextarena字段)链接。
nfreepools和ntotalpools存储有关当前可用池的信息。
freepools指针指向当前可用的池。
Arena结构简单,负责根据需要向池中分配内存。
当arena为空时,其内存将返回给操作系统。
gc模块是Python中内存管理的接口。
通常,Python程序员不需要担心程序中的内存管理问题。
检查程序是否有内存。
如果出现内存泄漏,可能需要使用gc模块接口来排查问题。
一些Python系统会关闭自动垃圾收集,让程序自行决定何时回收,但Instagram的系统却这么做了,据说整体运行效率提高了10%。
常用函数:
set_debug(flags):设置gc的调试日志。
通常设置为gc.DEBUG_LEAK以查看内存泄漏对象。
collect([Generation]):执行垃圾收集,循环引用的对象被回收。
该函数可以传递参数,0表示仅回收第0代的垃圾对象,1表示回收第0代和第1代的对象,2表示回收第0代、第1代和第2代的对象。
这表示回收。
如果不传递任何参数,则使用2作为默认参数。
get_threshold():获取gc模块的垃圾回收阈值。
返回的是一个元组,其中第0个是第0代的阈值,第1个是第1代的阈值,第2个是第2代的阈值。
set_threshold(threshold0[,threshold1[,threshold2]):设置垃圾收集阈值。
get_count():获取当前自动垃圾回收的计数器。
返回一个元组。
第0个是第0代中垃圾对象的数量,第1个是第0代链表遍历的次数,第二个是第1代链表遍历的次数。