Python 服务器应用程序内存泄漏
Python server app leaking memory
我正在尝试诊断我的 Python 服务器应用程序泄漏内存的原因。该应用程序接受图像请求 url 使用 Vips 调整其大小并 returns 图像。每次请求后,内存使用量大致按原始图像的大小增长。
from fapws import base
import fapws._evwsgi as evwsgi
from gi.repository import Vips
import urllib2
import hmac
import hashlib
import base64
import StringIO
from boto.s3.connection import S3Connection
from boto.s3.bucket import Bucket
def start():
evwsgi.start('0.0.0.0', '80')
evwsgi.set_base_module(base)
def lfrThumbnail(environ, start_response):
try:
parameters = environ['PATH_INFO'].split('/')
s3File = 'my s3 url' + parameters[0]
width = float(parameters[1])
height = float(parameters[2])
hmacSignatureUser = parameters[3]
hmacSignature = some hasing code...
if not (hmacSignatureUser == hmacSignature):
print hmacSignatureUser
print hmacSignature
print hmacSignatureUser == hmacSignature
raise Exception
bufferedImage = urllib2.urlopen(s3File).read()
image = Vips.Image.new_from_buffer(bufferedImage, '')
imageWidth = float(image.width)
imageHeight = float(image.height)
imageAspectRatio = imageWidth / imageHeight
if (width > imageWidth) or (height > imageHeight):
image = image
elif abs((imageAspectRatio / (width/height)) - 1) < 0.05:
image = image.resize(width / imageWidth)
else:
scaleRatioWidth = width / imageWidth
scaleRatioHeight = height / imageHeight
maxScale = max(scaleRatioWidth, scaleRatioHeight)
image = image.resize(maxScale)
cropStartX = (image.width - width) / 2
cropStartY = (image.height - height) / 2
image = image.crop(cropStartX, cropStartY, width, height)
except Exception, e:
start_response('500 INTERNAL SERVER ERROR', [('Content-Type','text')])
return ['Error generating thumbnail']
start_response('200 OK', [
('Content-Type','image/jpeg'),
('Cache-Control: max-stale', '31536000')
])
return [image.write_to_buffer('.jpg[Q=90]')]
evwsgi.wsgi_cb(('/lfr/', lfrThumbnail))
evwsgi.set_debug(0)
evwsgi.run()
if __name__ == '__main__':
start()
我试过使用 muppy,pympler 跟踪器,但图像 open/close 操作后的每个差异都显示只使用了几个字节。
外部 C 库可能是内存泄漏的原因吗?如果是这样,如何调试它。
如果有任何关联,我是 运行 python 服务器,位于 docker 容器中
我是 libvips 维护者。听起来像vips操作缓存:vips将最后几次操作保存在内存中,并在可能的情况下重用结果。在某些情况下,这可能是一个巨大的性能胜利。
对于 Web 服务,您可能会在其他地方进行缓存,因此您不会想要这个,或者您至少不会想要大型缓存。您可以通过 vips_cache_set_max()
和朋友控制缓存大小:
来自 Python 是:
Vips.cache_set_max(0)
完全关闭缓存。您可以将缓存设置为限制内存使用、文件描述符使用或操作数。
您可以设置一些其他有用的东西来观察资源使用情况。 Vips.leak_set(True)
使 vips 在退出时报告泄漏的对象,并报告峰值像素缓冲区内存使用情况。 Vips.cache_set_trace(True)
使其在调用时跟踪所有操作,并显示缓存命中。
在您的代码中,我还会启用顺序模式。将 access = Vips.Access.SEQUENTIAL
添加到您的 new_from_buffer()
。
默认行为是打开图像进行完全随机访问(因为 vips 不知道您最终会对图像进行哪些操作 运行)。对于像 JPG 这样的东西,这意味着 vips 将在打开时将图像解码为一个大的未压缩数组。如果图像小于 100mb,它会将此数组保留在内存中。
然而,对于简单的调整大小,您只需要从上到下访问像素,因此您可以在打开时提示顺序访问。在这种模式下,vips 只会从您的输入中一次解压缩几条扫描线,并且永远不会保留整个未压缩的图像。您应该会看到内存使用和延迟明显下降。
您可以处理许多其他事情,例如 exif 自动旋转、颜色管理、透明度、jpeg 加载时收缩,以及许多其他事情,我相信您知道。 vipsthumbnail
的来源可能是有用的参考:
https://github.com/jcupitt/libvips/blob/master/tools/vipsthumbnail.c
我正在尝试诊断我的 Python 服务器应用程序泄漏内存的原因。该应用程序接受图像请求 url 使用 Vips 调整其大小并 returns 图像。每次请求后,内存使用量大致按原始图像的大小增长。
from fapws import base
import fapws._evwsgi as evwsgi
from gi.repository import Vips
import urllib2
import hmac
import hashlib
import base64
import StringIO
from boto.s3.connection import S3Connection
from boto.s3.bucket import Bucket
def start():
evwsgi.start('0.0.0.0', '80')
evwsgi.set_base_module(base)
def lfrThumbnail(environ, start_response):
try:
parameters = environ['PATH_INFO'].split('/')
s3File = 'my s3 url' + parameters[0]
width = float(parameters[1])
height = float(parameters[2])
hmacSignatureUser = parameters[3]
hmacSignature = some hasing code...
if not (hmacSignatureUser == hmacSignature):
print hmacSignatureUser
print hmacSignature
print hmacSignatureUser == hmacSignature
raise Exception
bufferedImage = urllib2.urlopen(s3File).read()
image = Vips.Image.new_from_buffer(bufferedImage, '')
imageWidth = float(image.width)
imageHeight = float(image.height)
imageAspectRatio = imageWidth / imageHeight
if (width > imageWidth) or (height > imageHeight):
image = image
elif abs((imageAspectRatio / (width/height)) - 1) < 0.05:
image = image.resize(width / imageWidth)
else:
scaleRatioWidth = width / imageWidth
scaleRatioHeight = height / imageHeight
maxScale = max(scaleRatioWidth, scaleRatioHeight)
image = image.resize(maxScale)
cropStartX = (image.width - width) / 2
cropStartY = (image.height - height) / 2
image = image.crop(cropStartX, cropStartY, width, height)
except Exception, e:
start_response('500 INTERNAL SERVER ERROR', [('Content-Type','text')])
return ['Error generating thumbnail']
start_response('200 OK', [
('Content-Type','image/jpeg'),
('Cache-Control: max-stale', '31536000')
])
return [image.write_to_buffer('.jpg[Q=90]')]
evwsgi.wsgi_cb(('/lfr/', lfrThumbnail))
evwsgi.set_debug(0)
evwsgi.run()
if __name__ == '__main__':
start()
我试过使用 muppy,pympler 跟踪器,但图像 open/close 操作后的每个差异都显示只使用了几个字节。
外部 C 库可能是内存泄漏的原因吗?如果是这样,如何调试它。
如果有任何关联,我是 运行 python 服务器,位于 docker 容器中
我是 libvips 维护者。听起来像vips操作缓存:vips将最后几次操作保存在内存中,并在可能的情况下重用结果。在某些情况下,这可能是一个巨大的性能胜利。
对于 Web 服务,您可能会在其他地方进行缓存,因此您不会想要这个,或者您至少不会想要大型缓存。您可以通过 vips_cache_set_max()
和朋友控制缓存大小:
来自 Python 是:
Vips.cache_set_max(0)
完全关闭缓存。您可以将缓存设置为限制内存使用、文件描述符使用或操作数。
您可以设置一些其他有用的东西来观察资源使用情况。 Vips.leak_set(True)
使 vips 在退出时报告泄漏的对象,并报告峰值像素缓冲区内存使用情况。 Vips.cache_set_trace(True)
使其在调用时跟踪所有操作,并显示缓存命中。
在您的代码中,我还会启用顺序模式。将 access = Vips.Access.SEQUENTIAL
添加到您的 new_from_buffer()
。
默认行为是打开图像进行完全随机访问(因为 vips 不知道您最终会对图像进行哪些操作 运行)。对于像 JPG 这样的东西,这意味着 vips 将在打开时将图像解码为一个大的未压缩数组。如果图像小于 100mb,它会将此数组保留在内存中。
然而,对于简单的调整大小,您只需要从上到下访问像素,因此您可以在打开时提示顺序访问。在这种模式下,vips 只会从您的输入中一次解压缩几条扫描线,并且永远不会保留整个未压缩的图像。您应该会看到内存使用和延迟明显下降。
您可以处理许多其他事情,例如 exif 自动旋转、颜色管理、透明度、jpeg 加载时收缩,以及许多其他事情,我相信您知道。 vipsthumbnail
的来源可能是有用的参考:
https://github.com/jcupitt/libvips/blob/master/tools/vipsthumbnail.c