OpenCV Python:如何避免Python3中cv2.imwrite()的内存膨胀问题?
问题排查:Ubuntu 16.04 + OpenCV 3.4.1 Python应用内存膨胀问题
背景与问题场景
我正在排查一套运行在Ubuntu 16.04(x86)系统上的Python应用内存异常增长问题:
- 应用基于Python 3.5.2开发,使用本地编译的OpenCV 3.4.1
- 核心操作是频繁调用
cv2.imwrite()写入图像文件,运行过程中内存占用急剧上升,一开始怀疑是OpenCV的imwrite方法存在内存泄漏。
测试验证过程
为了定位问题,我写了一个极简的测试脚本,排除业务代码干扰:
#!/usr/bin/python3 import cv2 import time img = cv2.imread("vista.jpg") idx = 0 while True: filename = "/tmp/vista_copy_" + str(idx) + ".tiff" cv2.imwrite(filename, img) idx = idx + 1 time.sleep(1)
运行脚本的同时,我每10秒采样一次系统空闲内存:
$ while [ 1 ] ; do grep MemFree /proc/meminfo ; sleep 10 ; done MemFree: 898024 kB MemFree: 780640 kB MemFree: 667848 kB MemFree: 545700 kB MemFree: 437196 kB MemFree: 315820 kB MemFree: 298380 kB MemFree: 298292 kB MemFree: 297448 kB MemFree: 297080 kB MemFree: 915616 kB
排查关键发现
- 最初看到删除/tmp下的测试文件后内存立刻恢复,以为是程序没有正确关闭文件句柄,但查了OpenCV的C++源码没找到相关问题;
- 后来发现**/tmp是RAM磁盘**,但把写入路径换成以太网连接的外部驱动器、本地物理硬盘文件夹时,内存膨胀问题依然存在;
- 最终确认:这不是OpenCV
imwrite的问题,而是Linux系统的文件缓存机制导致的“假内存泄漏”——系统会自动缓存写入的文件内容,在内存充足的情况下不会主动释放这些缓存,导致内存占用看起来一直在增长。
解决方案
临时应急方案
如果需要快速缓解内存占用,可以定期执行命令手动清理系统缓存:
echo 3 > /proc/sys/vm/drop_caches
- 说明:
echo 3会同时清理页缓存、目录项和inodes缓存;如果只想清理页缓存(更温和),可以用echo 1 > /proc/sys/vm/drop_caches。
更温和的长期优化方案
1. 调整系统内核参数
通过修改/etc/sysctl.conf配置内核的缓存回收策略:
- 增加
vm.vfs_cache_pressure参数(默认值100,值越高,内核越倾向于回收目录项和inodes缓存):
这个配置会让内核在内存资源紧张时,优先回收文件系统缓存,而不是挤压应用程序的内存空间。echo "vm.vfs_cache_pressure=200" >> /etc/sysctl.conf sysctl -p
2. 代码层面主动提示内核释放缓存
在Python代码中,写入文件后可以调用系统API提示内核不需要缓存该文件内容:
#!/usr/bin/python3 import cv2 import time import os import posix img = cv2.imread("vista.jpg") idx = 0 while True: filename = "/tmp/vista_copy_" + str(idx) + ".tiff" cv2.imwrite(filename, img) # 通知内核可以释放该文件的缓存页 fd = os.open(filename, os.O_RDONLY) posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_DONTNEED) os.close(fd) idx += 1 time.sleep(1)
POSIX_FADV_DONTNEED标记会告诉内核,该文件的缓存内容不再需要,可以被回收,从而减少系统缓存的占用。
内容的提问来源于stack exchange,提问作者Paza
相关产品推荐
相关产品推荐

