python垃圾回收算法之引用计数

362 阅读2分钟

python垃圾回收主要采用的是引用计数为主,标记清除和分代回收为辅的策略。

1.引用计数(reference counting)

1.1 原理

python语言默认采取的垃圾回收机制是引用计数。其原理是:每个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数。每当新的引用对象指向该对象时,它的引用计数ob_ref加1;每当该对象的引用失效时,引用计数ob_ref减1。一旦对象的引用计数为0,该对象立即被回收,对象占用的内存空间将被释放。

1.2 引用计数查看

通过sys.getrefcount()来获取一个名称所引用的对象的引用计数情形

import sys
print(sys.getrefcount(123))
a=123
print(sys.getrefcount(123))

result:

7
8

1.2 引用计数增加的情形

对象被创建

x=5

对象被引用

a='people'
b=a

作为容器对象的一个元素

a='name'
list1 = [a, 'sex']

作为参数进行传递

a='name'
foo(a)

对对象使用sys.getrefcount()

import sys
print(sys.getrefcount(123))
a=123
print(sys.getrefcount(123))

result:

7
8

1.3 引用计数减少的情形

对象被删除

x=5
del x

对象的别名被赋值给其他对象

x ="aaa"

对象被从一个窗口中移除

list1 = ['name', 'sex']
list1.remove('sex')

对象离开了它的作用域 foo(x)函数结束后

def func(x):
    return x**2

窗口对象被销毁

list1 = ['name', 'sex']
del list1

1.4 优缺点

1.4.1 优点

引用计数法具有明显的优点,比如高效、实现逻辑简单、具备实时性,一旦一个对象的引用计数归零,内存就直接释放了。不用像其他机制等到特定时机。将垃圾回收随机分配到运行的阶段,处理回收内存的时间分摊到了平时,正常程序的运行比较平稳。

1.4.2 缺点

引用计数的第一个缺点是实现麻烦。每个对象都需要分配单独的空间来统计引用计数,需要浪费空间,且需要对引用计数进行维护,维护时容易出错。

引用计数的第二个缺点是在一些场景下可能运行比较慢。正常来说垃圾回收会平稳运行,但是当需要释放一个比较大的对象(如字典),需要对引用的所有对象循环嵌套调用,从而会花费比较长的时间。

引用计数的第三个缺点是循环引用,引用计数无法解决该问题。