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
跟踪内存使用,程序运行结果:
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
。。。
可以看出内存占用在逐渐变大,新建了一个对象后,没有释放
这个例子会产生内存泄漏
,原因是:
class Foo
的实例f
创建了一个循环引用:f.bar
指向f
本身f
如果被其他变量引用,可以保护f
不被回收- 但
f.bar
也引用了f
,形成循环引用,即使外部变量不再引用f
,f
的内存也无法回收,导致内存泄漏
2. gc.collect 手动回收
使用 gc
模块手动回收垃圾
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
。。。
可以看出内存的使用恒定在某个数值,不再增大了。