对象:因为Python中一切皆对象,所以变量的本质其实就是对象的一个指针;比如:a = 1
其实先分配内存(创建对象)存储数据“1”;然后a变量中指向对象(变量a存储着对象的内存地址)
不可变对象:变量相对于对象的指向不会发生改变
1.具有相同值的不可变对象,变量指向的是同一个对象
2.只要不可变对象的值发生改变,变量就会指向重新创建的对象
可变对象:变量相对于对象的指向会发生改变
1.具有相同值的可变对象,变量指向的是不同的对象
2.允许可变对象存储数据的值发生改变而不影响变量的指向
因为Python运行过程中会使用各种变量,所以如果对象的占用内存管理不当,程序会由于内存溢出而异常终止
1.引用计数法
Python中采用引用计数
为主,标记-清除
和分代回收
为辅的策略
引用计数法:每当对象被引用一次引用计数
就会加一;而当引用被销毁后就会进行减一,当引用计数
为零时进行内存回收
优点
1.高效且易于实现
2.实时性:一旦没有引用,内存直接释放
3.对象拥有确定的周期
缺点
1.资源消耗:维护引用计数的次数和引用赋值成正比
2.无法解决循环引用问题
2.标记-清除
标记-清除
阶段1:GC将所有的活动对象打上标记
阶段2:GC把没有被打上标记的非活动对象进行回收
活动检测
对象之间相互引用构成一张有向图,从根对象出发遍历有向图,可达或间接可达的对象标记为活动对象,其他作为非活动对象进行回收
缺点:必须顺序扫描整个堆内存,找出活动和非活动对象
PyGC:使用不同的链表来持续追踪活跃对象,每创建一个对象都会被加入到零代链表中;随后会进行“检测循环引用”根据规则减掉相互引用对象的引用计数,将引用计数为0的进行回收,剩下的活跃对象移动到一代链表中。
Python何时进行标记回收过程?
PyGC阙值:被分配计数值与被释放计数值的差值达到设定阙值的时候进行标记回收,一代链表中遵循同样的方法,将活跃对象移动到二代链表中。
3.分代回收
分代回收:如果一个内存对象在某次Mark过程中发现不是垃圾,那么它短期内成为垃圾的可能性就很小。分代收集将那些在多次垃圾收集过程中都没有被标记为垃圾对象的内存对象集中到另外一个区域——年老的区域,即这个区域中的内存对象年龄比较大。因为年老区域内内存对象短期内变成垃圾的概率很低,所以这些区域的垃圾收集频率可以降低,相对的,对年轻区域内的对象进行高频率的垃圾收集。这样可以提高垃圾收集的整体性能。
PyGC:引用分代回收,一个代就是一个链表,所有属于同一个代的内存块都链接在同一个链表中(总共三代);每个代中有对象数量上限,每创建的对象都会被加入到到零代中并检查零代是否满,如果满就开始进行垃圾回收
PyGC设计三"代"且通过阙值(时间)和对象数量上限(空间)完成了“标记-清除”和“分代回收”这两种GC思想,异曲同工之妙。
参考
- 博客1:https://www.jianshu.com/p/1e3...[英文翻译]
- 博客2:https://blog.csdn.net/xiongch...[附源码]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。