python中垃圾回收
Python中一切皆对象,一切变量,本质上是对象的一个指针。那么,如何知道一个对象不再被调用了?
当这个对象的引用计数(指针数)为0的时候,说明这个对象不可达,就成了垃圾,需要回收。
import sys, gc
# a引用计数1
a = []
# a引用计数2
print(sys.getrefcount(a))
# b引用计数1
b = []
# 形参也占用,引用计数2
def func(item):
# 引用计数3
print(sys.getrefcount(b))
#引用计数4
func(b)
查看应用计数的方式,getrefcount本身也会算一次
查看内存使用情况,下面代码linux下运行
import os
import psutil
def show_memory_info(initial):
pid = os.getpid()
p = psutil.Process(pid)
info = p.memory_full_info()
memory = info.uss / 1024. / 1024
print('{} memory_used {} MB', format(initial, memory))
def func():
show_memory_info('start')
a = [i for i in range(1000000)]
show_memory_info('after a created')
func()
show_memory_info('end')
引用计数的缺点,循环引用
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
当出现上面情况的时候,即使不在有对象调用list1、list2引用,引用计数也为1,所占用的内存永远无法被回收,会导致内存泄漏。
import gc, sys
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)
print(sys.getrefcount(list1))
print(sys.getrefcount(list2))
del list1
del list2
# 手动垃圾回收
print(gc.collect())
# 3
# 3
# 2
垃圾回收参考自:https://www.cnblogs.com/franknihao/p/7326849.html
调试内存泄漏
import objgraph
a = [1, 2, 3]
b = [4, 5, 6]
a.append(b)
b.append(a)
objgraph.show_refs([a])
dot转图片:https://onlineconvertfree.com/zh/
总结
- python中自带垃圾回收机制
- 引用计数是其中最简单的实现方式,但不是充分必要条件,循环引用需要手动回收
- python的自动回收算法包括标记清楚和分代收集,主要针对的是循环引用的垃圾收集
- 调试内存泄露,objgraph是很好的可视化工具。