【Python】在rk3588开发板排查内存泄漏问题过程记录
背景介绍:
实时视频检测程序,可支持多路视频流实时目标检测等操作。在服务器上运行正常,移植到RK3588,并开发基于rknn的推理模块。在测试期间发现内存泄露的问题,使用top指令长期观察,内存平均以约5%每小时的速度增长;
第一阶段分析:
- 整个程序包含了获取帧图片、AI推理图片、图片绘制结果信息、保存图片、队列推送告警等环节;图片内存堆积可能造成内存泄漏;
- 疑惑点:python自身具备GC自动回收机制,使用完的图片应该会慢慢自动回收;在服务器运行程序时,并未发现内存泄漏;
第一阶段操作:
- 目前图片在程序内主要以cv2的格式存在。手动
del
释放所有程序内已经使用完全的图片数据,特别需要关注使用copy()的图片数据。
例如:
第二阶段分析:
调整过后,发现程序的内存上涨速度变慢,但是每小时仍以0.5~1%的速度增长。目前没有想到存在泄漏风险的地方,决定使用一些排查内存泄漏的工具来查看。
第二阶段操作:
在主线程中定时监控当前进程的内存占用:
简单示例:
import psutil, os, timepid = os.getpid()
proc = psutil.Process(pid)while True:mem_mb = proc.memory_info().rss / 1024 / 1024print(f"[{time.strftime('%H:%M:%S')}] Memory: {mem_mb:.2f} MB")time.sleep(10) # 每 10 秒采样一次
然后再锁定泄漏对象类型
安装 objgraph:
pip install objgraph
在主线程定期调用:
import objgraph
objgraph.show_growth(limit=20)
它会告诉你哪种对象数量一直在涨,例如:
ndarray 50000 +1000
dict 1200 +200
Frame 800 +50
如果是 ndarray → 大概率是 OpenCV / numpy 图像数据没释放
如果是 dict / list → 可能是缓存或队列没清
如果是自定义类 → 检查你的推理 / 线程代码
然后再代码中主线程的修改如下:
打印结果如下:
然后可以看到Letter_Box_Info
对象始终稳定增长,这是一个内存泄露的点。
排查发现,这是Letter_Box_Info
是rknn推理模块中引用第三方代码里,创建的一个对象。
泄露原因:COCO_test_helper对象的letter_box_info_list数组内不断加入Letter_Box_Info对象,却没有主动释放,导致letter_box_info_list数组长度不断增加。
解决方案:在每次rknn推理结束后手动释放:
修改后重新运行程序:
没有发现新的泄漏对象
后续
内存泄漏速度进一步降低,说明排查内存泄漏的方式是有效的。
修改后运行程序,运行很长一段时间后,内存泄漏以低于0.5%的速度增长,但是以上方式没有再排查到内存泄漏,后续有新进展会补充。
现阶段,采用进程定期重启的方式可以暂时解决这个问题,目前设置的24小时重启一次的策略,凌晨执行,不易感知。