2012-01-17 9 views
3

実験的なブロブストアファイルAPIを使用して、いくつかのイベントデータを含む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) 

プロセスは、以上のメモリ140メガバイトを使用したアボートする前に、このコードはしばらくイベントループの周りを約20倍にそれを作るには。イベントは、このアプリケーション固有のデータベースモデルです。イベントは基本的にリモートマシン上で起こっていることの記録ですが、後でこれらのイベントはmap reduce操作によって処理され、統計情報を構築します。今はただダウンロードしたいだけです。私たちのデータベースには1000種類のイベントが100種類あります(後でそれを別々に保存することに変わりますが、今のところこれがそれです)。それぞれの私はf.open原因f.closef.close()がちょうどf.write(..)と呼ばれるこのコードの以前のインスタンス化f.__exit__()

によって呼び出された通りに、句で終了するたびに呼び出されることに注意し

要素は 'StringIO'に書き込まれます。この以前のバージョンでは、メモリが不足していましたが、それ以外は同様に動作しました。このコードにはメモリをリークさせる何かが残っています。

ヘルプ?

更新 は、私はちょうど(buf.getvalue())f.writeをコメントアウトしようとしました、それは明らかにそれには何もしてブロブストアアイテムを作成しませんが、それがすべて処理された最終的に完了しませんイベントエンティティ。私は何かを見逃しているか、またはf.write()リークメモリかfinalize()まですべてをバッファリングしますか?

+1

「イベント」とは何ですか? AppEngineオブジェクトですか? –

+0

「元のバージョン」は何をしましたか?それが何をしたのかわからなくても、「早急に解決する」ことを知ることは役に立ちません。 –

+0

ありがとうございます。私はより明確な情報を提供するために質問を編集しました。 – Jules

答えて

1

f.write(buf.getvalue())に電話をするときには、StringIOに1つのメモリオブジェクトに変換して渡すように要求しています。それは高価になるでしょう。

buf.seek(0)を試してください。ストリームの先頭に巻き戻され、ちょうどf.write(buf)を渡します。 StringIOはファイルのようなオブジェクトで、f.writeはそれをストリームとして読み取ることができます。

sourceを見ると、file_service_pb.AppendRequestがStringIOを処理できるかどうかは、ドキュメントまたはコードからはわかりません。それを試してみてください。

+0

有用な観察、私はそれと遊ぶでしょう。しかし、 'buf.getvalue()'は文字列の一時的なコピーを作らなければならないかもしれませんが、これは非効率ですが、漏れてはいけません。それは、メモリが足りなくなる前にループを20回以上丸める。私が切り替えると、ピークメモリが低くなるため余分な時間がかかることがありますが、全体的な問題を解決するものではありません。 – Jules

+0

あなたの ''ファイル '"は、独自のバッファを格納しているかもしれません。現時点で確認する立場ではありませんが、GAEファイルオブジェクトで 'flush'メソッドを探してみてください。 – Joe

関連する問題