【发布时间】: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