【发布时间】:2015-10-09 10:49:31
【问题描述】:
我认为ndb 库中存在内存泄漏,但我找不到位置。
有没有办法避免下面描述的问题?
您是否有更准确的测试想法来找出问题所在?
这就是我重现问题的方式:
我创建了一个包含 2 个文件的极简 Google App Engine 应用程序。app.yaml:
application: myapplicationid
version: demo
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /.*
script: main.APP
libraries:
- name: webapp2
version: latest
main.py:
# -*- coding: utf-8 -*-
"""Memory leak demo."""
from google.appengine.ext import ndb
import webapp2
class DummyModel(ndb.Model):
content = ndb.TextProperty()
class CreatePage(webapp2.RequestHandler):
def get(self):
value = str(102**100000)
entities = (DummyModel(content=value) for _ in xrange(100))
ndb.put_multi(entities)
class MainPage(webapp2.RequestHandler):
def get(self):
"""Use of `query().iter()` was suggested here:
https://code.google.com/p/googleappengine/issues/detail?id=9610
Same result can be reproduced without decorator and a "classic"
`query().fetch()`.
"""
for _ in range(10):
for entity in DummyModel.query().iter():
pass # Do whatever you want
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World!')
APP = webapp2.WSGIApplication([
('/', MainPage),
('/create', CreatePage),
])
我上传了一次名为 /create 的应用程序。
之后,每次调用/ 都会增加实例使用的内存。直到由于错误Exceeded soft private memory limit of 128 MB with 143 MB after servicing 5 requests total 而停止。
注意:这个问题可以用webapp2以外的其他框架重现,比如web.py
【问题讨论】:
-
我想应该是ndb in-context cache。
-
我对 python 一无所知,但阅读您的代码我会说您的内存不足,因为您的
ndb.put_multi试图在单个事务中插入 100 个实体。这可能是导致分配这么多内存的原因。超出软私有内存限制可能是因为当您的下一个请求增加内存负载时,您的事务仍在运行。如果您在调用之间等待一段时间(分别等待事务完成),则不应发生这种情况。如果响应时间急剧增加,App Engine 也应该启动一个额外的实例。 -
@DanielRoseman “上下文缓存仅在单个线程的持续时间内持续存在。”如果您清除上下文缓存或设置禁用缓存的策略,内存使用量增加得更慢,但泄漏仍然存在。
-
@konqi 调用
MainPage而不是CreatePage时发生内存泄漏。 -
@greg 哦,我的错。如果主页获取数据存储中存在的所有内容的 10 倍,那不会导致高内存消耗吗?如果您清除数据存储区,问题是否仍然存在?
标签: python google-app-engine memory-leaks app-engine-ndb webapp2