【问题标题】:matplotlib rendering to png slow, but only in complex flask appmatplotlib 渲染为 png 缓慢,但仅在复杂的烧瓶应用程序中
【发布时间】:2020-09-10 19:06:13
【问题描述】:

我有一个将一些数据显示为 png 的 Flask 应用程序。下面是一个简单的虚拟示例:

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO

import logging
logger = logging.getLogger(__name__)

def specimage():
    plt.clf()
    plt.plot(np.arange(3000), np.random.random(3000), drawstyle="steps-post")
    plt.loglog()
    out = BytesIO()
    logger.debug("Rendering...")
    plt.savefig(out, format='png')
    logger.debug("Done rendering")
    out.seek(0)
    return out.getvalue()

如果我以交互方式运行它,该函数可能需要 1 秒才能运行。但如果我从烧瓶应用程序中调用它:

import render
@app.route('/getfig')
def getfig():
    return Response(render.specimage(), content_type="application/png")

现在调用savefig 至少需要 15 秒,CPU 始终保持在 100%!

如果我将此视图插入到一个非常基本的 Flask 应用程序中,它会以合理的速度运行。但我的应用程序相当复杂。我在哪里可以找到可能会大大降低 matplotlib 速度的奇怪交互?

编辑 更多可能相关的信息。在渲染图像时,应用程序启动了一个单独的线程来执行一些冗长的计算。看起来图像生成挂起,直到另一个线程完成。

那么这就提出了一个问题,为什么 matplotlib 卡住了?我可以访问我的烧瓶应用程序中的任何其他视图,它会立即返回,因此通常线程工作正常。我在这里遇到了一些奇怪的 GIL 问题吗?另一个线程正在做一些 zlib 压缩,我认为 PNG 也使用 zlib,所以,也许这就是问题所在?

EDIT2 从另一个线程中删除 zlib 调用没有帮助,所以这不是 zlib 的错。另一个线程没有调用任何matplot函数,但它与绘图线程在同一个模块中,这意味着matplotlib.pyplot被导入那里......

【问题讨论】:

  • 你是在本地运行烧瓶应用吗?
  • @PaulH 是的。围绕savefig 的调试语句确认这是有问题的部分,而不是任何类型的网络延迟
  • 你能在你的日志语句之外做一个plt.draw()来隔离是渲染还是保存?
  • 我还能够将它作为一个非常基本的烧瓶应用程序运行,而且它是即时的。我认为如果不对代码有更深入的了解,就不可能回答这个问题。你碰巧有可用的回购吗?
  • plt.draw() 也很慢

标签: python matplotlib flask


【解决方案1】:

回复:

  1. Matplotlib 方面,savefig():您可以确保关闭它:plt.close()

  2. Flask 方面:您可以使用:Flask-Caching

    from flask_caching import Cache
    cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
    app = Flask(__name__)
    cache.init_app(app)
    @app.route("/")
    @cache.cached(timeout=55)
    def index():
    ................
    

【讨论】:

    猜你喜欢
    • 2020-10-18
    • 2023-04-07
    • 2012-01-30
    • 2022-01-25
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 2019-07-19
    相关资源
    最近更新 更多