有很多不同的方法来实现垃圾回收,例如跟踪,引用计数,转义分析,时间戳和心跳信号等。不同的语言依赖于不同的垃圾回收实现,例如,有些将其与编译器和运行时系统集成在一起。而其他语言则可能需要事后设置,甚至可能需要重新编译。Python中垃圾收集器使用基于引用计数的方法。它在程序执行期间运行,并在对象的引用计数达到0时开始工作。

1、引用管理

首先,内存管理是基于引用的管理。我们知道Python中,引用与对象是分离的,一个对象可以有多个引用,而每个对象都存有指向自己的引用计数。可以使用标准库sys查看某个对象的引用计数:

from sys import getrefcount

a = [1,2,3]
print(getrefcount(a)) # 打印2 b = a
print(getrefcount(a)) # 打印3

由于调用getrefcount()时又创建了一次引用,所以打印的引用计数会比实际多一个。

2、对象引用对象

Python中对象会引用别的对象,而容器对象的引用会构成很复杂的拓扑结构:

l = [1,2,3]
d = {"k": l} y = [l, d]
z = [y,(l,y)]

使用 objgraph 包可以绘制引用关系:

...
import objgraph
objgraph.show_refs([z], filename='sample-graph.png')

绘制的 z 对象的引用图如下:

3、引用环

两个对象相互引用,即构成了所谓的引用环

a = []
b = [a]
a.append(b) objgraph.show_refs([a,b], filename='a-b.png')

即使是单个对象,只需自己引用自己,也会构成引用环:

a = []
a.append(a) objgraph.show_refs([a], filename='a-b.png')

del关键字除了可以删除容器中的元素,还可以删除某个引用。

4、垃圾回收

CPython中的内存管理和垃圾回收有两个策略:

  • 引用计数

  • 分代回收

4.1 引用计数

CPython中主要的垃圾收集机制是通过引用计数,且引用计数无法被禁用,而后面谈到的分代回收策略则可以禁止。

原理上,Python的某个对象的引用计数变为0时,就要成为被回收的垃圾了。例如:

a = [1,2,3]
del a

当垃圾回收启动时,Python扫描到这个引用计数为0的对象,会将其所占据的内存清空。而垃圾回收是个费时费力的事,垃圾回收期间Python不能进行其他任务。频繁的垃圾回收会大大降低Python的效率,所以Python只会在特定条件下启动垃圾回收。Python运行时,会记录其中分配对象和取消分配对象的次数,当两者差值高于某个阈值,垃圾回收才会启动。

有人说引用计数是一个穷人的垃圾收集器。它确实有一些缺点,包括无法检测到循环引用。但是,引用计数的优点是,你可以在没有引用的情况下立即删除该对象。

4.2 分代回收

除了上面这种实时的自动的基于引用计数的垃圾回收实现方法,Python还同时采用分代回收策略,这一次略的基本假设是,存活时间越久的对象,越不可能在以后成为垃圾。Python将所有对象分为三代,所有新建对象都是0代,如果经过一次扫描没被回收即成为了1代,以此类推。

Python的基于引用计数的方法是自动的,并且是实时发生的,而分代垃圾回收模块的操作是周期性的,可以手动调用,常用API:

  • get_shreshold()方法可以查看触发垃圾收集的阈值:

  • gc.get_count()方法可以查看内存中当前存在的各代对象数量

  • gc.set_threshold()方法可以更改触发垃圾收集的阈值

>>> import gc
>>> print(gc.get_threshold()) # (700, 10, 10)
>>> gc.set_threshold(700.10,5) # 2代垃圾回收会更频繁
>>> gc.collect() # 手动触发垃圾回收

对于每一代,垃圾收集器模块都有一个阈值对象。如果对象数超过该阈值,则垃圾收集器将触发收集过程,在该过程中幸存下来的对象会被归为下一代。默认情况下,Python对于最年轻的一代的阈值为700,对于两个较老的一代中的每个阈值为10。

引用环的回收

分代回收策略可以可以检测和解决引用环问题,在Python 1.5中引入了循环检测算法,它跟踪容器对象,即可以容纳其他对象(例如列表,字典,类等)的对象,因为只有它们才能创建此这种引用环。

循环检测算法的基本原理是:Python会复制每个对象的引用计数,记为gc_ref。假设每个对象为i,该对象的计数为gc_ref_i。Python会遍历所有的对象i,对于每个对象i所引用的对象j,将jgc_ref_j减1:

遍历后,gc_ref不为0的对象及这些对象引用的对象,以及更下游的对象会被保留,而引用环中的对象会被回收。

参考

Python:垃圾回收的更多相关文章

  1. Python垃圾回收机制--完美讲解!

    转自: http://www.jianshu.com/p/1e375fb40506 先来个概述,第二部分的画述才是厉害的. Garbage collection(GC) 现在的高级语言如java,c# ...

  2. python垃圾回收机制与小整数池

    python垃圾回收机制 当引用计数为0时,python会删除这个值. 引用计数 x = 10 y = x del x print(y) 10 引用计数+1,引用计数+1,引用计数-1,此时引用计数为 ...

  3. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  4. python 垃圾回收

    # 垃圾回收 # 小整数对象池 # a = 100# python对小整数的定义是[-5,257],这些证书对象是提前创建好的,不会被垃圾回收,再一个python的程序中,所有位于这个范围内的正式使用 ...

  5. python垃圾回收

    python垃圾回收 python垃圾回收主要使用引用计数来跟踪和回收垃圾.在引用计数的基础上,通过“标记—清除”解决容器对象可能产生的循环引用问题,通过“分代回收”以空间换时间的方法提高垃圾回收效率 ...

  6. 《垃圾回收的算法与实现》——Python垃圾回收

    Python垃圾回收 python采用引用计数法进行垃圾回收 Python内存分配 python在分配内存空间时,在malloc之上堆放了3个独立的分层. python内存分配时主要由arena.po ...

  7. python垃圾回收机制(Garbage collection)

    由于面试中遇到了垃圾回收的问题,转载学习和总结这个问题. 在C/C++中采用用户自己管理维护内存的方式.自己管理内存极其自由,可以任意申请内存,但也为大量内存泄露.悬空指针等bug埋下隐患. 因此在现 ...

  8. python 垃圾回收详解

    原文:https://zhuanlan.zhihu.com/p/31150408 总纲 策略和垃圾回收系统工作内容 引用计数详解 标记-清除+分代收集 循环引用 编程应用-常见方法 ex 过程详解 使 ...

  9. python垃圾回收算法

    标准python垃圾回收器由两部分组成,即引用计数回收器和分代垃圾回收器(即python包中的gc module).其中,引用计数模块不能被禁用,而GC模块可以被禁用. 引用计数算法 python中每 ...

  10. python 垃圾回收笔记

    目录 引用计数 python内部的引用计数机制 循环引用 调试内存泄漏 总结 python 程序在运行的时候,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量:计算完成后,再将结果输出到永久性 ...

随机推荐

  1. JPG学习笔记1(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  2. 使用LCX进行内网端口转发

    Lcx.exe是一个端口转发工具,相当于把目标服务器A上的3389端口转发到具有外网ip地址的B机上(即我们自己的主机或是已经控制的主机),这样链接B机的3389端口就相当于链接A机的3389端口了, ...

  3. 一分钟搞懂JavaScript中的JSON对象

    JSON(JavaScript Object Notation)是表示值和对象的通用格式. JavaScript 提供了如下方法: JSON.stringify 将对象转换为 JSON. JSON.p ...

  4. 【GitChat首秀:限时免费】互联网测试岗校招的那些事儿

    2020 校园秋招即将结束,2021 校招春招即将开始. 作为一名扎根互联网近十年的资深测试开发,我刚经历过数十个测试岗位的校招笔试和面试选拔.在 2020 年秋招面试过程中,我深深地感受到" ...

  5. 微信小程序-显示外链图片 bug

    微信小程序-显示外链图片 bug 显示外链图片 bug 403 bug 禁止外链,未授权 https://httpstatuses.com/403 image component 图片.支持 JPG. ...

  6. iPadOS 14 memoji 无法使用 bug

    iPadOS 14 memoji 无法使用 bug iPadOS 14 bug refs 如何在 iPhone 和 iPad Pro 上使用动话表情 https://support.apple.com ...

  7. expo-cli & React Native

    expo-cli https://reactnative.dev/docs/environment-setup You will only need a recent version of Node. ...

  8. Captain technology开发的新能源汽车强在哪里?

    在新能源汽车飞速发展的这些年,Captain technology 认识到,要改变有状况,就要不断创新,调整新能源汽车发展路线.新能源汽车本质永远是汽车, Captain technology是在改变 ...

  9. 画一个PBN大角度飞越转弯保护区

      今天出太阳了,尽管街上的行人依旧很少,但心情开始不那么沉闷了.朋友圈里除了关注疫情的最新变化之外,很多人已经开始选择读书或是和家人一起渡过这个最漫长的春节假期.陕西广电网络春节期间所有点播节目一律 ...

  10. mysql数据库表引入redis解决方案

    缓存方案 缓存方案在我的另外一篇博客里有详细说明,地址:https://www.cnblogs.com/wingfirefly/p/14419728.html 数据结构: 方案1: 1.存储结构采用h ...