美文网首页
进阶学习8-垃圾回收

进阶学习8-垃圾回收

作者: 龙猫六六 | 来源:发表于2020-01-31 15:25 被阅读0次

总结

描述 备注
引用计数 对象被赋值给变量,引用计数+1;引用计数为0,会被系统垃圾回收
标记清除 不可达(从一个节点遍历,不可达的对象进行释放)
分代收集 对象分为3代,本轮没有被回收的对象,放入下一代
objgraph 排查内存泄漏

垃圾回收

引用计数

  • 对象无法被删除,一般通过系统进行垃圾回收进行删除,垃圾回收的判断依据为引用计数
  • 引用计数系统函数sys.getrefcount(val),统计一个对象被引用的次数

手动释放内存

  • 删除变量对对象的引用,del a
  • 强制调用gc.collect(),清理没有引用的对象 'gc.collect()'

import gc

show_memory_info('initial')

a = [i for i in range(10000000)]

show_memory_info('after a created')

del a
gc.collect()

show_memory_info('finish')
print(a)

########## 输出 ##########

initial memory used: 48.1015625 MB
after a created memory used: 434.3828125 MB
finish memory used: 48.33203125 MB

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-12-153e15063d8a> in <module>
     11 
     12 show_memory_info('finish')
---> 13 print(a)

NameError: name 'a' is not defined

标记清除(不可达)

对于一个有向图,如果从一个节点出发进行遍历,并标记其经过的所有节点;那么,在遍历结束后,所有没有被标记的节点,我们就称之为不可达节点。显而易见,这些节点的存在是没有任何意义的,自然的,我们就需要对它们进行垃圾回收。

分代收集

Python 将所有对象分为三代。刚刚创立的对象是第 0 代;经过一次垃圾回收后,依然存在的对象,便会依次从上一代挪到下一代。而每一代启动自动垃圾回收的阈值,则是可以单独指定的。当垃圾回收器中新增对象减去删除对象达到相应的阈值时,就会对这一代对象启动垃圾回收。事实上,分代收集基于的思想是,新生的对象更有可能被垃圾回收,而存活更久的对象也有更高的概率继续存活。因此,通过这种做法,可以节约不少计算量,从而提高 Python 的性能。

调试内存泄漏 objgraph

一个非常好用的可视化引用关系的包
mac按照步骤

  • pip install objgraph python安装objgraph
  • pip install xdot python安装xdot
  • brew install graphviz brew安装graphviz,用于将dot文件转换为pngdot objgraph-plfv1m1h.dot -T png -o pic.png

实例

import objgraph

a = [1, 2, 3]
b = [4, 5, 6]

a.append(b)
b.append(a)

objgraph.show_backrefs([a])

如下图为引用关系,

  • a指向list 4items,
  • b指向list 4items;
  • list 4items存在循环引用


    image.png

相关文章

网友评论

      本文标题:进阶学习8-垃圾回收

      本文链接:https://www.haomeiwen.com/subject/llugthtx.html