python内存泄漏问题的一种处理方法

2023-07-10 14:28:15 浏览数 (2)

1. 内存泄漏例子

代码语言:javascript复制
import tracemalloc 

class Foo:
	def __init__(self):
		self.arr = list(range(1000000))
		self.bar = self
		
tracemalloc.start()

# Run your code
for i in range(10000):
	f = Foo()

	current_mem, peak_mem = tracemalloc.get_traced_memory()
	print(f"Current memory usage is {current_mem / 10**6}MB")
	print(f"Peak was {peak_mem / 10**6}MB")

tracemalloc.stop()

使用 tracemalloc 跟踪内存使用,程序运行结果:

代码语言:javascript复制
Current memory usage is 36.993044MB
Peak was 36.993112MB
Current memory usage is 73.986112MB
Peak was 73.98618MB
Current memory usage is 110.979124MB
Peak was 110.979192MB
Current memory usage is 147.972136MB
Peak was 147.972204MB
Current memory usage is 184.965148MB
Peak was 184.965216MB
Current memory usage is 221.958232MB
Peak was 221.958232MB
Current memory usage is 258.951316MB
。。。

可以看出内存占用在逐渐变大,新建了一个对象后,没有释放

这个例子会产生内存泄漏,原因是:

  1. class Foo 的实例f创建了一个循环引用:f.bar指向f本身
  2. f如果被其他变量引用,可以保护f不被回收
  3. f.bar也引用了f,形成循环引用,即使外部变量不再引用ff的内存也无法回收,导致内存泄漏

2. gc.collect 手动回收

使用 gc 模块手动回收垃圾

代码语言:javascript复制
import tracemalloc 
import gc

class Foo:
	def __init__(self):
		self.arr = list(range(1000000))
		self.bar = self

tracemalloc.start()

first_enter_loop = True

# Run your code
for i in range(10000):
	f = Foo()

	current_mem, peak_mem = tracemalloc.get_traced_memory()
	print(f"Current memory usage is {current_mem / 10**6}MB")
	print(f"Peak was {peak_mem / 10**6}MB")

	if not first_enter_loop:
		gc.collect()  # 手动回收垃圾
		print(f"released, Current memory usage is {current_mem / 10**6}MB")
	first_enter_loop = False

tracemalloc.stop()

输出结果:

代码语言:javascript复制
Current memory usage is 36.993044MB
Peak was 36.993112MB
Current memory usage is 73.986112MB
Peak was 73.98618MB
released, Current memory usage is 73.986112MB
Current memory usage is 73.986531MB
Peak was 73.986531MB
released, Current memory usage is 73.986531MB
Current memory usage is 73.986603MB
Peak was 73.986781MB
released, Current memory usage is 73.986603MB
Current memory usage is 73.986603MB
Peak was 73.986853MB
。。。

可以看出内存的使用恒定在某个数值,不再增大了。

0 人点赞