Python 高级知识 垃圾收集

垃圾回收

现代的语言基本上都是自带垃圾收集器,简称GC. GC的优点在于可以自动的对程序中不再需要使用的资源进行回收,GC主要目的是节约计算机资源,防止内存泄露等.

熟悉Java的中高级开发者,一般都是比较了解一些常见java垃圾收集器的.

JDK 版本

典型GC

Oracle JDK7

CMS

Oracle JDK8

G1

Oracle JDK11

ZGC

IBM J9

Balanced GC

Azul JDK

C4

垃圾收集资源时

判活算法主要是:

  • 引用计数算法(java不用)

  • 可达性算法(java 使用)

内存整理算法主要是:

  • 标记-清理

  • 标记-整理

  • 标记-复制

此外还有一些时间维度,空间维度上的收集策略:

  • 分代年龄收集

  • 内存分区(G1 GC)

这些GC技术灵活的组合,满足各种场景下的性能需求. 一般而言,Java性能的体现主要就是java字节码二次JIT,JVM内部运行时优化和垃圾收集策略调整. 借助这些技术,Java实现了接近C++的速度,一般经过充分预热后的Java程序可以很可靠的应对一些性能优先场景的挑战

对于Python而言,性能是无法和一些静态编辑语言相比的,比如C/C++,即使对比大部分的JVM语言,Python也有非常大的差距. 本质原因除了Python的解释特性外,还有就是它的标准运行时Cpython的解释速度和垃圾收集优化比较简单. 这里没有论及那种语言优劣的意思,每种语言有自己的哲学和侧重点,Python讲的时开发效率和语法本身的优雅层度,运行效率不是第一的考虑.

Python GC模型

Python GC的模型很简单:

  • 判活算法: 引用计数算法为主,标记清除为辅. python判活算法中的标记清除跟一般的标记清除还是有点差别的,全名是局部标记清除,它基于引用计数

内存整理算法

  • 标记-清理

时间维度:

  • 分代年龄收集

Python没有任何的收集技术组合,CPython只暴露了少了的C API

https://docs.python.org/zh-cn/3/library/gc.html?highlight=gc#module-gc

 

分析:

引用计数法时最简单的资源判活算法,但是这种算法如果不结合一些特殊逻辑是无法满足实际的判活需求的,因为有循环引用的问题. 一旦出现循环引用就会出现失效资源无法被正确判活导致永远不会被收集的情况. 所以python采用引用计数算法为主,标记清除为辅的策略,引用技术法模型简单,实现难度低,同时标记清除在垃圾收集过程中辅助识别循环引用

 

Python采用了“标记-清除”(Mark and Sweep)算法,解决容器对象可能产生的循环引用问题。(注意,只有容器对象才会产生循环引用的情况,比如列表、字典、用户自定义类的对象、元组等。而像数字,字符串这类简单类型不会出现循环引用。作为一种优化策略,对于只包含简单类型的元组也不在标记清除算法的考虑之列)

 

python gc 接口

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import gc
import sys
 
a1 = 'A1'
# 在使用sys.getrefcount()函数时,函数会引用一次,在使用参数引用时,参数会引用一次,同时参数会自动产生一个临时引用,所以会比预期的引用次数多1
# 查询a1被引用的数量
print("a1's refcount", sys.getrefcount(a1))
l1 = [1, a1]
# 查询a1被引用的数量
print("a1's refcount", sys.getrefcount(a1))
# 查询l1被引用的数量
print("l1's refcount", sys.getrefcount(l1))
# 获取a1被哪些对象引用
print(gc.get_referrers(a1))
# 获取l1引用了哪些变量
print(gc.get_referents(l1))

结果

a1's refcount 3
a1's refcount 4
l1's refcount 2
[{'__name__''__main__''__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002527B851E88>, '__spec__': None, '__file__''D:/workspace/self/python3/lesson01/HelloWorld.py''__builtins__': <module 'builtins' (built-in)>, 'gc': <module 'gc' (built-in)>, 'sys': <module 'sys' (built-in)>, 'a1''A1''l1': [1'A1']}, (0, None, 'A1'"a1's refcount"1"l1's refcount"), [1'A1']]
['A1'1]

其实python的垃圾收集,除非是专业写C 扩展,一般python开发都不需要使用.因为没有什么调优的必要,全部是CPython的默认设置.即使要调优也没有几个参数可调整的.还是享受Python的开发效率吧,别刻意去作这方面的事情

posted @ 2021-09-26 10:46  旁人X  阅读(37)  评论(0)    收藏  举报