Python服务器应用程序内存泄漏

2024-10-03 15:21:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试诊断为什么我的Python服务器应用程序会泄漏内存。应用程序接受一个图像url请求,使用Vips调整其大小并返回图像。在每次请求之后,内存使用量大致按原始图像的大小增长。在

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跟踪器,但是在图像打开/关闭操作之后,每个diff都只显示使用了几个字节。在

外部C库是内存泄漏的原因吗?如果是这样的话,如何调试它呢。在

如果有什么关系的话,我在docker容器中运行python服务器


Tags: 内存from图像imageimportfloatwidthstart
1条回答
网友
1楼 · 发布于 2024-10-03 15:21:27

我是libvips的维护者。这听起来像是vips操作缓存:vips将最后几个操作保存在内存中,并尽可能重用结果。在某些情况下,这可能是一个巨大的性能胜利。在

对于web服务,您可能在其他地方缓存,所以您不希望这样做,或者您至少不需要大型缓存。您可以使用vips_cache_set_max()和朋友控制缓存大小:

http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsOperation.html#vips-cache-set-max

来自Python,它是:

Vips.cache_set_max(0)

完全关闭缓存。可以根据内存使用、文件描述符使用或操作数将缓存设置为限制。在

您可以设置一些其他有用的东西来监视资源使用情况。Vips.leak_set(True)使VIP在退出时报告泄漏的对象,并报告峰值像素缓冲区内存使用情况。Vips.cache_set_trace(True)使其跟踪调用的所有操作,并显示缓存命中。在

在您的代码中,我还将启用顺序模式。将access = Vips.Access.SEQUENTIAL添加到new_from_buffer()中。在

默认行为是打开图像进行完全随机访问(因为VIP不知道您将在图像上运行什么操作)。对于JPG这样的东西,这意味着vips将在开放时将图像解码为一个大的未压缩数组。如果图像小于100mb,它将把这个数组保存在内存中。在

但是,对于简单的调整大小,您只需要从上到下访问像素,因此您可以在打开时提示顺序访问。在这种模式下,VIP只会一次从你的输入中解压一些扫描线,而不会保存整个未压缩的图像。你应该会看到内存使用和延迟的下降。在

还有很多其他的事情你可以处理,像exif自动旋转,颜色管理,透明度,jpeg压缩加载,以及许多其他的,我相信你知道。vipsthumbnail的源可能是一个有用的参考:

https://github.com/jcupitt/libvips/blob/master/tools/vipsthumbnail.c

相关问题 更多 >