python内存监控工具memory_profiler和guppy的用法

python2.7在内存管理上相比python3还是有些坑的,其释放后的内存仍然保留在python的内存池中,不被系统所用。python循环引用的变量不会被回收,这会导致程序越运行,占用的内存越大。我在跑py-faster-rcnn的demo时,基本上跑2000张图像,16g内存就要爆了。于是尝试用python的内存监控工具来调试程序,找到不能膨胀的变量,然后del之,再手动回收内存gc.collec()

下面是我用的两个内存监视工具,一个是按每行代码查看内存占用的工具memory_profiler,一个是查看占用内存前十位变量的工具guppy。

1. memory_profiler

首先是安装:

pip install -U memory_profiler

然后用profile修饰想要查看的函数名:如:

@profile
def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    my_func()

输出结果:

Line #    Mem usage  Increment   Line Contents
==============================================
     3                           @profile
     4      5.97 MB    0.00 MB   def my_func():
     5     13.61 MB    7.64 MB       a = [1] * (10 ** 6)
     6    166.20 MB  152.59 MB       b = [2] * (2 * 10 ** 7)
     7     13.61 MB -152.59 MB       del b
     8     13.61 MB    0.00 MB       return a
memory_profiler功能强大,更多功能可以看 官网这里

2. guppy

首先安装:

pip install guppy

然后import下

from guppy import hpy
hxx = hpy()
heap = hxx.heap()
byrcs = hxx.heap().byrcs; 

在主程序下增加:

print(heap)

输出示例:

Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  10124  22 81944416  95  81944416  95 list
     1  16056  34  1325464   2  83269880  96 str
     2   9147  20   745616   1  84015496  97 tuple
     3    102   0   366480   0  84381976  98 dict of module
     4    287   1   313448   0  84695424  98 dict of type
     5   2426   5   310528   0  85005952  98 types.CodeType
     6   2364   5   283680   0  85289632  99 function
     7    287   1   256960   0  85546592  99 type
     8    169   0   192088   0  85738680  99 dict (no owner)
     9    123   0   142728   0  85881408  99 dict of class

可以看到第一个list占了95%的内存,若print(heap)在主程序的循环中,可以查看每次循环后的变量内存占用情况。

输入以下命令,查看这个占内存最大的list中的数据类型:

byrcs[0].byid

最后测试后发现,test.py下get_im_blob等函数占用内存不断增大,每检测一副图像,该函数增加6-10MB内存开销。但奇怪的是用guppy查看前十个变量,并没有发现哪个变量有明显的内存增大迹象。于是猜测可能是每张图像推理后,推理的结果bbox,label,img等数据保存在了内存中,这样方便所有图像推理结束后,plt.show().于是修改程序,每张图像推理后,plt.show()一下。用memory_profiler发现内存不再继续增大,interesting!其实把plt.show()改成plt.close()也可以防止内存不断增大。具体原因肯定是python 的内存回收机制规则导致的。



### 设置或修改 Jupyter Notebook 的内存限制 对于 Jupyter Notebook 来说,其本身并没有直接提供用于设定整个应用程序级别的内存限制选项。然而,在某些情况下可以采取间接措施来控制内存在特定环境中的使用情况。 #### 控制 Python 进程的资源分配 当通过命令行启动 Jupyter Notebook 时,默认会依赖于操作系统对进程管理的方式以及所使用的Python解释器版本等因素共同决定可用资源量。如果希望更精细地调整单个Notebook Kernel所能消耗的最大物理RAM大小,则可以通过Linux下的`ulimit`指令或者Windows的任务计划程序等方式预先限定子进程中允许访问的最大堆栈尺寸等参数[^1]。 另外一种方法是在创建虚拟环境中指定最大可使用的内存: ```bash pip install memory_profiler psutil guppy3 ``` 接着可以在代码里加入监控并强制终止超出限额的情况: ```python from memory_profiler import profile import os, signal def handler(signum, frame): print('Memory limit exceeded') exit(0) signal.signal(signal.SIGTERM, handler) @profile(per_call=True) def func(): # Your code here if __name__ == '__main__': func() ``` 这段脚本利用 `memory_profiler` 库跟踪函数执行期间的内存变化趋势,并配合信号处理机制实现超限自动退出功能[^2]。 需要注意的是上述方案并不能完全杜绝所有类型的内存泄漏问题发生;而且因为涉及到底层操作系统的权限设置等问题可能并不适用于所有的部署场景下应用。因此建议开发者们平时多注意编写高效合理的算法逻辑结构以减少不必要的开销才是最根本有效的解决方案[^3]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值