开发者

Python进程使用内存后不释放的解决

目录
  • 背景
  • Process 类
  • 常见问题 
  • 解决办法
  • 总结

背景

使用python进行大量的数据操作过程中RSS占用(几个G,Python的GC会频繁地malloc/free),发现RSS内存不释放。

  • 排查代码后,没有发现内存泄露的情况,GC也是默认开启的,甚至代码将数据库数据读出来遍历一遍后程序结束,内存一直存在不释放。
  • 使用tracemalloc,objectgraph调试,Python对象的产生和释放并没有啥异常。
  • Python的对象内存管理是基于引用计数的(refcnt为0直接decref回收),python内存池也没发现大内存驻留,操作系统brk和mmap也并没有不释放内存。

在调测中也发现,这个问题给人的整体感觉不是代码哪里有问题,查阅相关资料后,发现可能是Glibc优化问题。

python的内存机制,频繁通过系统调用获取和释放内存对性能消耗很大的,python将对象销毁后,并没有立即将这部分内存返回给操作系统,而是加到了自己维护的空闲内存池中。

从系统层面来看,这步扥内存已经被python进程占用了,但是从python解释器的角度来看,这部分是free的,可以用于生成新的对象。

那么我们在Python中如何手动分配释编程客栈放内存?

我们使用android进程内存隔离的能力直接管理内存,父进程只负责进程池管理,子进程干完事情,直接退出,或过期重新拉起,或者超过内存阈值就干掉,就可以了(当然最好是业务处理不是很频繁的情况下)。

多进程处理参考:multiprocessing --- 基于进程的并行 — Python 3.10.0 文档

Process 类

在 multiprocessing 中,通过创建一个 Process 对象然后调用它的 start() 方法来生成进程。 

Process 和 threading.Thread API 相同。

一个简单的多进程程序示例是:

from multiprocessing import Process
 
def f(name):
    print('hello', name)
 
if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

常见问题 

实际业务中会经常用到数据库等长连接的操作,如数据库等,

可能会报如下错误:

ERphpROR:base.py:Line 705:_finalize_fairy:Exception during reset or similar

 

Traceback (most recent call last):

  File "/home/tsalazar/.cache/pypoetry/virtualenvs/ufos--PZandroid7y9g--py3.8/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 697, in _finalize_fairy

    fairy._reset(pool)

 

  File "/home/tsalazar/.cache/pypoetry/virtualenvs/ufos--PZ7y9g--py3.8/lib/python3.8/site-packages/sqlalchemy/pool/base.py", line 893, in _reset

    pool._dialect.do_rollback(self)

 

  File "/home/tsalazar/.cache/pypoetry/virtualenvs/ufos--PZ7y9g--py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 558, in do_rollback

    dbapi_connection.rollback()

 

psycopg2.OperationalError: SSL error: decryption failed or bad record MAC

解决办法

不要将长连接对象通过参数传递,在函数内部链接,使得进程之间互不影响。 

总结

以上为个人经验,javascript希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜