有没有了解 paddleocr 的 V 友,我用 Flask 写了个简易 API,内存占用会越来越大, 4~6 个小时就把机器 64GB 内存占满了,只能用 cron 每小时重启,是内存泄露的问题吗

44 天前
 drymonfidelia

这是我的代码,因为我平时 python 写得少,不熟练,如果代码质量差请别喷

import json, re
import uuid
from urllib.parse import quote, unquote
import yaml
import os, urllib.request
import time
from flask import Flask, config, render_template, request, redirect, make_response

from paddleocr import PaddleOCR, draw_ocr

ocr = PaddleOCR(use_angle_cls=True, lang='en')

app = Flask(__name__)


@app.route('/ocr', methods=['GET'])
def do_ocr():
    if request.method == 'GET':
        data = request.args
    if 'url' in data:
        url = unquote(data['url'])
    else:
        return ""
    tmp_path = f"/dev/shm/{uuid.uuid4()}"
    urllib.request.urlretrieve(url, tmp_path)
    result = ocr.ocr(tmp_path, cls=True)
    data = ""
    for recr in result:
        rec = recr[1][0].upper()
        data += rec + ","
    os.remove(tmp_path)
    return data.strip(",")


if __name__ == '__main__':
    app.run()

ocrapi.py 是从别处复制来的猴子补丁(不然好像并发会有问题)

from gevent import monkey, pywsgi

monkey.patch_all()

from app import app

用了 supervisor 启动:

[program:ocrapi]
command=gunicorn --workers 6 --worker-class=gevent --worker-connections=50 -b 0.0.0.0:8080 ocrapi:app
directory=/opt/ocrapi/
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/ocrapi.log
loglevel=info

服务启动时内存占用在 2GB 左右,随后越来越大

另外想问下如果只是用于识别包装盒上的产品序列号(大写英文数字组成,位数固定,手机拍照的,白底黑字/黑底白字都有可能)有效果更好的方案吗?

1935 次点击
所在节点    Python
23 条回复
ggvm
44 天前
查一下具体的内存是被什么东西占用了?

估计是模型被多次加载,但从来不释放?
Puteulanus
44 天前
ocr = PaddleOCR(use_angle_cls=True, lang='en')
这个要是放 do_ocr 里面呢

我之前看别人另一个识别的用的 https://cnocr.readthedocs.io/zh/latest/usage/
drymonfidelia
44 天前
@Puteulanus 如果是这个要放进去的原因,为什么放外面反而会被多次加载?放外面不是更应该不会被多次加载么?
Puteulanus
44 天前
@drymonfidelia 我的意思是既然感觉 PaddleOCR 有问题,就别维持它的全局对象了,没有引用看垃圾回收能不能收了它
est
44 天前
@drymonfidelia 可能是 ocr 对象维持了一些历史记录。你扫一次内存就占着不释放了。
ClericPy
44 天前
如果对这个库不了解, 可以在子进程里初始化它, 子进程销毁的时候就清理了. 不过估计会慢... 优化的地方很多
drymonfidelia
44 天前
@Puteulanus 但是每次 ocr 都加载一次模型感觉会很慢
kaneg
44 天前
/dev/shm/这个是在内存的,会不会文件没有删掉,滞留在内存了
drymonfidelia
44 天前
@kaneg 我看 top 是 gunicorn 这个进程占的内存
drymonfidelia
44 天前
@kaneg 不过你提醒我了 /dev/shm/ 确实堆了 10GB 的图没删掉,不知道为什么,不过影响不大
infun
44 天前
@drymonfidelia 怎么会影响不大。。。这里应该用 with 自动管理
drymonfidelia
44 天前
@infun with 能实现代码块结束自动删除文件么
kuanat
44 天前
paddleocr 内存分配管理有问题是个很长时间的问题了。我印象官方 github 有几个 issues 就是讨论这个的,而且跨了多个版本,你可以去查一下。

之前有说是因为框架缓存的原因,有人说不是。我之前遇到这个问题也是通过重启来解决,尝试读了一下 c++ 代码部分还是太复杂了,没有解决的精力和能力。
infun
44 天前
bringyou
44 天前
如#13 所言,paddle OCR 的内存占用是个老问题,可以看 issue
https://github.com/PaddlePaddle/PaddleOCR/discussions/6977
bringyou
44 天前
也可以手动调用 try_shrink_memory 来释放内存
ON9
44 天前
一定要用猴子吗,用 fastapi 呢
NoOneNoBody
44 天前
python 多进程会将全局环境复制到每个子进程
flask 我不清楚要怎么做,最好使用 cache 而不是全局变量,然后每个子进程调用时从 cache 懒加载读取
Eished
44 天前
我也是 Flask+paddleocr ,用的 CPU 版本,1G 内存,都是小图片,大概半年才会内存满了重启一次
founddev
43 天前
可以尝试 paddleocr 转 onnx 用 PyTorch ,TF 或者 tensorrt 这种比较成熟的框架,尽量不要使用受众很小的这种框架,有 bug 都不一样会改

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1030071

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX