美文网首页
python拾遗7 - 垃圾回收

python拾遗7 - 垃圾回收

作者: 天命_风流 | 来源:发表于2020-05-05 16:06 被阅读0次

    垃圾回收机制

    相比 C++ 的手动回收内存,python 的垃圾回收机制可谓是省心省力,判断是否回收一块内存,主要有三点:

    1 计数引用

    也就是最为常见的回收方式,当对一块内存的引用计数为 0 时,证明没有方法再调用这块内存,执行回收。

    另你可以使用 sys.getrefcount( a ) 来查看一个变量的引用情况

    2 标记清除

    上面的方式非常简单,但是 python 的回收机制没有这么简单,当产生循环引用的时候,第一种方法就无能为力了:

    def func():
        show_memory_info('initial')
        a = [i for i in range(10000000)]
        b = [i for i in range(10000000)]
        show_memory_info('after a, b created')
        a.append(b)
        b.append(a)
    
    func()
    show_memory_info('finished')
    
    ########## 输出 ##########
    
    initial memory used: 47.984375 MB
    after a, b created memory used: 822.73828125 MB
    finished memory used: 821.73046875 MB
    

    这时,我们要使用标记清除算法,我们可以用图的概念理解它:对一个有向图,如果从一个指定的结点出发,遍历所有结点,并进行标记。遍历结束后,没有被标记的节点就是不可达节点。
    显然,这种不可达的节点是没有意义的,我们可以回收它的内存。

    3 分代收集

    引用专栏中的话解释:

    而分代收集算法,则是另一个优化手段。

    Python 将所有对象分为三代。刚刚创立的对象是第 0 代;经过一次垃圾回收后,依然存在的对象,便会依次从上一代挪到下一代。而每一代启动自动垃圾回收的阈值,则是可以单独指定的。当垃圾回收器中新增对象减去删除对象达到相应的阈值时,就会对这一代对象启动垃圾回收。

    事实上,分代收集基于的思想是,新生的对象更有可能被垃圾回收,而存活更久的对象也有更高的概率继续存活。因此,通过这种做法,可以节约不少计算量,从而提高 Python 的性能。

    4 手动删除

    • 使用 del a 删除一条引用
    • 使用 gc.collect( ),触发一次垃圾回收 ,回收内容包括上面三点。

    调试内存引用

    使用 objgraph 模块,可以生成一个可视化的引用关系图。

    • objgraph.show_refs() 函数
    import objgraph
    
    a = [1, 2, 3]
    b = [4, 5, 6]
    
    a.append(b)
    b.append(a)
    
    objgraph.show_refs([a])
    
    引用关系
    • objgraph.show_backrefs( ) 函数
    import objgraph
    
    a = [1, 2, 3]
    b = [4, 5, 6]
    
    a.append(b)
    b.append(a)
    
    objgraph.show_backrefs([a])
    
    这个函数展示的信息更加全面

    相关文章

      网友评论

          本文标题:python拾遗7 - 垃圾回收

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