2

Когда я запускаю запрос на большом множестве небольших объектов (объекты 15k с несколькими короткими строковыми и логическими свойствами), не делая ничего с этими объектами, я постоянно вижу использование памяти экземпляра (увеличение на 70 Мб). Увеличение памяти не выглядит пропорциональным количеству данных, которые ему когда-либо нужно хранить в памяти только для запроса.Ошибка использования памяти приложения App Engine DB

Петля я использую следующее:

cursor = None 
while True: 
    query = MyModel.all() 
    if cursor: 
    query.with_cursor(cursor) 
    fetched = 0 
    for result in query.run(batch_size = 500): 
    fetched += 1 

    # Do something with 'result' here. Actually leaving it empty for 
    # testing to be sure I don't retain anything myself 

    if fetched == 500: 
     cursor = query.cursor() 
     break 
    else: 
    break 

Чтобы быть уверенным, что это не из-за Appstats, я называю appstats.recording.dont_record() не записывать какие-либо статистику.

Кто-нибудь знает, что может быть? Или любые указатели на то, как отлаживать/профилировать это?

Update 1: Я включил gc.set_debug(gc.DEBUG_STATS) на производстве код, и я вижу, что сборщик мусора вызывается регулярно, так что это пытается собрать мусор. Когда я вызываю gc.collect() в конце цикла (также конец запроса); он возвращает 0, и не помогает.

Update 2: Я сделал некоторые взлома, чтобы получить гуппи работать на dev_appserver, и это, казалось, указывают, что после явного gc.collect() в конце цикла, большая часть памяти была поглощена в «Словаре из google.appengine.datastore.entity_pb.Property.

ответ

1

Я сообщил об этом команде разработчиков приложений, и они, похоже, подтверждают, что это на самом деле проблема (предположительно, с обработкой курсоров).

+0

у вас возникла проблема с командой GAE? Если да, то можете ли вы опубликовать ссылку? Вчера я спросил необычно похожий вопрос о SO: http://stackoverflow.com/questions/32877705/how-is-memory-garbage-collected-in-app-engine-python-when-iterating-over-db-re/ 32883298 # 32883298 – tom

+0

Я нашел его: https://code.google.com/p/googleappengine/issues/detail?id=12243 – tom

2

В каждой модели объекта есть над головой.

Вы запрашиваете объекты возврата в качестве Protobufs для стартеров.

Итак, вы получите ряд протобофов для набора результатов.

Затем он декодируется. Каждый декодированный объект включает имена свойств, а также данные для каждого объекта. У вас есть 15K объектов. Насколько велики ваши имена свойств, например.

Таким образом, у вас есть как минимум две копии результирующего набора в памяти в различных формах (возможно, больше), не включая ничего, что вы делаете с экземплярами класса модели.

У вас код/​​цикл не имеет возможности для сборщиков мусора, и это может произойти позже.

Посмотрите на инструменты, такие как apptrace, чтобы помочь профилировать память.

+0

Я предполагаю, что у меня есть около 500 символов для имен свойств + значения, объединенные, так скажем 1k. Хранение всего в памяти действительно дало бы мне около 15 мегабайт, поэтому пару раз действительно составляло бы до 60 мегабайт. Но зачем нужно хранить все это в памяти? Можете ли вы рассказать о том, как вы можете сказать, что в сборках мусора нет такой возможности? Могу ли я заставить сбор мусора использовать 'gc.collect()' в цикле или после цикла? (Я попробовал первое, это не имело никакого эффекта, так что это должно означать, что я не понимаю, почему данные не собираются). – Remko

+0

Кроме того, я попробовал apptrace, но это, похоже, больше не работает в последних установках dev_appserver. – Remko

+0

Я сомневаюсь, что gc.collect будет делать что-либо реальное значение, пока запрос не завершится. Попытайтесь называть это самой последней до завершения запроса. Я бы предложил две вещи. 1.отойти от db и ndb, там есть ряд преимуществ. 2. Зачем перебирать все 15K-сущности - пересмотреть то, чего вы пытаетесь достичь. –

Смежные вопросы