使用BlobReader(Google App Engine,Python 2.7)进行内存泄漏

时间:2013-06-29 15:09:22

标签: python google-app-engine

在Google AppEngine中使用Python 2.7,为了向客户端提供 patched 二进制文件,我这样做:

  • 使用BlobReader
  • 从blobstore读取原始文件
  • 将数据从BlobReader输出到补丁点
  • 输出修补的字节
  • 输出原始数据的其余部分

系统有效,但似乎某处存在内存泄漏,因为在每次请求之后,当前实例使用的内存增加了两倍于blob的大小:例如。如果blob是8 MB,请求后实例使用的内存增加16 MB。因此,在几次这样的请求之后,实例被GAE强制终止,并出现“超出软私有内存限制”的错误消息。

以下是产生内存泄漏的代码的缩短版本:

class CurrentVer(db.Expando):
    "singleton entity with reference to the blob and starting position of the patch"
    patch_start = db.IntegerProperty()
    blob = blobstore.BlobReferenceProperty()

def out_blob(handler):
    # prepare a patch string
    patch_string = "<CONFIG><A>A316</A></CONFIG>"
    # read blob key and starting position of patch
    CurrVer = CurrentVer.get_by_key_name("CurrentVer")
    patch_start  = CurrVer.patch_start
    blob_key = str(CurrVer.blob.key())
    CurrVer = None
    # open BlobReader object with 1MB buffer, as shown in GAE docs:
    blob_reader = blobstore.BlobReader(blob_key, buffer_size=1048576)       
    # read original data until patch point, and output it:
    handler.response.out.write(blob_reader.read(patch_start))           
    # output patch bytes
    handler.response.out.write(patch_string)
    # skip the bytes that have been patched
    blob_reader.seek(patch_start + len(patch_string))
    # read remaining original data until the end, and output it
    handler.response.out.write(blob_reader.read())
    blob_reader.close()
    blob_reader = None
    gc.collect()

def gc_collect(webapp2.RequestHandler):
    def get(self):
        gc.collect()
        self.response.out.write("<html><body>Called cg.collect()</body></html>")

class patch_blob(webapp2.RequestHandler):
    def get(self):
        out_blob(self)

app = webapp2.WSGIApplication([('/patch_blob.*', patch_blob),
    ('/gc_collect.*', gc_collect)], 
    debug=True)

当代码运行时(URL = / patch_blob),在每个请求之后,实例使用的内存增加了blob大小的两倍,如下所示:

请求1:55 MB

请求2:73 MB

请求3:90 MB

...依此类推,直到我在日志中收到此错误:

(c)在为5个请求提供服务后,超过140.504 MB的软私有内存限制

(w)处理完此请求后,发现处理此请求的进程使用了​​太多内存并被终止。这可能会导致新进程用于您的应用程序的下一个请求。如果经常看到此消息,则可能是应用程序中存在内存泄漏。

任何人都可以解释发生了什么,以及如何避免看起来像一个令人震惊的内存泄漏? (幸运的是,GAE在触发错误之前仍然提供最后一个请求,但我确信这是一件不可取的事情,我想避免它......)

感谢!!!

0 个答案:

没有答案