Запись больших файлов в хранилище BLOB-объектов и нехватка памяти - PullRequest
3 голосов
/ 17 января 2012

Я использую экспериментальный API файла blobstore для записи файла CSV, содержащего некоторые данные о событиях.Там много данных, поэтому я собираю записи.Мой код выполняется в бэкэнде, поэтому у меня много времени, но у меня не хватает памяти, и я не понимаю, почему.

Вот код:

from __future__ import with_statement
from google.appengine.api import files

q = Event.all()

events = q.fetch(50)
while events:
    with files.open(blobname, 'a') as f:
        buf = StringIO()

        for event in events:
            buf.write(event.id)
            buf.write(',')
            buf.write(`event.logged`)
            buf.write(',')
            buf.write(event.type)
            buf.write(',')
            buf.write(event.timestamp)
            buf.write(',')

            needAmpersand = False
            for prop in event.dynamic_properties():
                if needAmpersand:
                    buf.write('&')
                needAmpersand = True
                buf.write(prop + '=' + str(getattr(event, prop)))
            buf.write('\n')

        f.write(buf.getvalue())
        buf.close()

    events = q.fetch(50)

files.finalize(blobname)

Этокод обходит цикл while в течение 20 раз, прежде чем процесс прерывается, использовав более 140 мегабайт памяти.Событие - это модель базы данных, специфичная для этого приложения.Событие - это, в основном, запись того, что происходит на удаленной машине, позже эти события будут обрабатываться с помощью операции сокращения карты для создания статистики, а пока я просто хочу их скачать.В нашей базе данных есть 100 из 1000 событий (позже мы также переключимся на их хранение по-другому, но пока это так).

Я отмечаю, что с f.open вызывает f.close, чтобы вызыватьсякаждый раз, когда он завершает предложение with, так как f.close() вызывается f.__exit__()

Более раннее создание этого кода, называемого просто f.write (..) для каждого элемента, который записывается в 'StringIO',Эта более ранняя версия исчерпала память намного быстрее, но в остальном вела себя аналогично.В этом коде все еще есть что-то, что вызывает утечку памяти.

Справка?

Обновление Я только что попытался закомментировать f.write (buf.getvalue)()) и хотя он, очевидно, не создает элемент хранилища BLOB-объектов, в котором есть что-либо, он в конечном итоге завершает обработку всех сущностей Event.Я что-то упускаю или f.write () теряет память или буферизирует все до finalize ()?

1 Ответ

1 голос
/ 18 января 2012

Когда вы вызываете f.write(buf.getvalue()), вы просите StringIO превратить себя в один объект памяти и передать его. Это будет дорого.

Попробуйте buf.seek(0), который вернется назад к началу потока и просто пропустит f.write(buf). StringIO - это файловый объект, и f.write должен быть в состоянии прочитать его как поток.

Посмотрите на источник , из документов или кода не ясно, может ли file_service_pb.AppendRequest иметь дело со StringIO. Попробуй.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...