在Google AppEngine中使用Python 2.7,为了向客户端提供 patched 二进制文件,我这样做:
系统有效,但似乎某处存在内存泄漏,因为在每次请求之后,当前实例使用的内存增加了两倍于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在触发错误之前仍然提供最后一个请求,但我确信这是一件不可取的事情,我想避免它......)
感谢!!!