zoukankan      html  css  js  c++  java
  • python之垃圾回收机制

    一、前言

    Python 是一门高级语言,使用起来类似于自然语言,开发的时候自然十分方便快捷,原因是Python在背后为我们默默做了很多事情,其中一件就是垃圾回收,来解决内存管理,内存泄漏的问题。

    内存泄漏:当程序不停运行,有一部分对象没有作用,但所占内存没有被释放,服务器内存随时间越来越少,最终导致系统的崩溃,所以内存泄漏是一个需要重点关注的问题。

    Java垃圾回收 半自动 只买新的 不用管扔垃圾
    Python全自动 【引用计数,分代回收】
    二、python的垃圾回收机制包括引用计数、循环引用,那么我们通过什么来解决呢,下面讲一下。

    2.1 引用计数

    Python 标记一个对象是否还有用的方法就是用引用计数,以下情形会为该对象的计数+1:

    创建时
    被引用时
    作为参数传入函数时
    相反,以下情形会为该对象的计数-1:

    被del
    被重引用
    函数执行完毕
    查看某一元素的计数可以通过 sys.getrefcount(),当引用计数为0 的时候,内存就会被释放。

    可以想到和其他垃圾回收相比,Python的机制优点很明显,就是实时性,Python的gc 模块就是开放的接口用以管理。

    也可以很容易猜到这样的缺点就是性能相对较低,看过这样的报道,instagram 通过禁用 gc 模块,性能提升10%!

    2.2 循环引用

    有一种特殊情况,当两个或多个变量互相循环引用的时候,按照计数引用的机制就无法处理了

    Python

    a = []

    b = []

    a.append(b)

    b.append(a)

    print(a,b)

    a,b 的引用计数均为2,无法回收两者内存

    2.3 解决方案

    通过 ”标记-清除“ 来解决循环调用问题:
    垃圾回收器定时去寻找这类循环调用,并清除

    具体是 先从 根对象集合副本中 开始寻找,这些对象计数不为0,没有被清除

    然后一个个检测,将其分为可达对象和不可达对象,底层通过链表的数据结构实现,通过操作副本清除标记,来在不影响原数据的情况下,判断是否为循环调用

    最后将不可达对象清除,释放内存,效率较低。

    有三种情况会触发垃圾回收:

    1.调用gc.collect(),

    2.当gc模块的计数器达到阀值的时候。

    3.程序退出的时候

    2.分代回收,利用 “空间换时间”策略提高效率:

    有些内存块生存时间从开始到结束,有些则很短,所以同样对他们进行垃圾回收是很浪费的一件事情,

    所有对象开始被划分到零代中,Python 默认 有三代,一个代就是一个链表

    年轻代中的对象优先处理,经历垃圾处理次数愈多的,越“老” ,就会上升,最终放在第二代中。

    需要研究:

    Python的垃圾回收机制是通过检测数量是否到达阈值来决定是否进行。

    gc模块

    补充:语录
    C中指针之类的 其实是操作系统的概念 c的抽象程度和os同级别
    C是os的好基友
    因此c的难度不在于困惑人的语法
    本质上是os复杂度的延伸
    Python作为动态语言 抽象程度更高 没有指针这种东西
    树上算法 遍历之类的 离不开树
    递归回溯和分治是初学者最容易困惑的
    比如图论算法离不开图的数据结构
    数据结构方便存 根本上还是方便算。

  • 相关阅读:
    Solr4.8.0源码分析(16)之SolrCloud索引深入(3)
    Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2)
    Solr4.8.0源码分析(14)之SolrCloud索引深入(1)
    Solr In Action 笔记(4) 之 SolrCloud分布式索引基础
    Solr In Action 笔记(3) 之 SolrCloud基础
    change buffer太复杂了
    mtr语言真是逆天了
    mysql自动化测试第一个例子
    mysql mtr写入数据
    垃圾规范
  • 原文地址:https://www.cnblogs.com/yx12138/p/11029311.html
Copyright © 2011-2022 走看看