Penso che ci sia una perdita di memoria nella libreria ndb
ma non riesco a trovare dove.Perdita di memoria nella libreria ndb di Google
C'è un modo per evitare il problema descritto di seguito?
Hai un'idea più precisa dei test per capire dove si trova il problema?
È così che ho riprodotto il problema:
ho creato un minimalista applicazione Google App Engine con 2 file.
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),
])
ho caricato l'applicazione, chiamata /create
una volta.
Successivamente, ogni chiamata a /
aumenta la memoria utilizzata dall'istanza. Fino a quando non si arresta a causa dell'errore Exceeded soft private memory limit of 128 MB with 143 MB after servicing 5 requests total
.
Esempio di grafico di utilizzo della memoria (si può vedere la crescita della memoria e va in crash):
Nota: Il problema può essere riprodotto con un altro quadro di webapp2
, come web.py
Probabilmente il [NDB cache in-context] (https://cloud.google.com/appengine/docs/python/ndb/cache), mi aspetto. –
Non conosco niente di Python ma leggendo il tuo codice direi che stai esaurendo la memoria perché il tuo 'ndb.put_multi' tenta di inserire 100 entità in una singola transazione. Questo è probabilmente ciò che causa l'allocazione di molta memoria. Il superamento del limite di memoria privata limitata è probabilmente dovuto al fatto che le transazioni sono ancora in esecuzione quando la richiesta successiva viene aggiunta al carico di memoria. Ciò non dovrebbe verificarsi se si attende un po 'tra le chiamate (rispettivamente attendere fino al completamento della transazione). Anche App Engine dovrebbe avviare un'istanza aggiuntiva se i tempi di risposta aumentano drasticamente. – konqi
@DanielRoseman "La cache nel contesto persiste solo per la durata di un singolo thread." Se si cancella la cache nel contesto o si imposta un criterio per disabilitare la memorizzazione nella cache, l'utilizzo della memoria aumenta più lentamente ma la perdita persiste. – greg