3

小さなオブジェクトの大規模なセット (いくつかの短い文字列とブール プロパティのみを持つ 15k オブジェクト) に対してクエリを実行すると、これらのオブジェクトに対して何もせずに、インスタンスのメモリ使用量が継続的に増加します (70Mb 増加)。メモリの増加は、クエリのためだけにメモリに保持する必要があるデータの量に比例しているようには見えません。

私が使用するループは次のとおりです。

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()、統計を記録しないように呼び出します。

何が起こっているのか、誰にも手がかりがありますか? または、これをデバッグ/プロファイルする方法に関する指針はありますか?

更新 1 :gc.set_debug(gc.DEBUG_STATS)プロダクション コードを有効にしましたが、ガベージ コレクターが定期的に呼び出されているので、ガベージを収集しようとしています。gc.collect()ループの最後 (リクエストの最後でもあります) でa を呼び出すと、 ; を返し0、役に立ちません。

更新 2 : guppy を dev_appserver で動作させるためにいくつかのハッキングを行いましたが、これはgc.collect()、ループの最後の明示的な後、ほとんどのメモリが「google.appengine.datastore.entity_pb の辞書」によって消費されたことを示しているようです。 。財産'。

4

2 に答える 2

2

各モデル エンティティにはオーバーヘッドがあります。

クエリを実行すると、最初にオブジェクトが Protobufs として返されます。

したがって、結果セットの一連のバッチ処理された protobuf が作成されます。

その後、デコードされます。デコードされた各エンティティには、プロパティ名と各エンティティのデータが含まれます。15K のエンティティがあります。たとえば、プロパティ名の大きさ。

したがって、モデル クラスのインスタンスで行うその他の処理を含めずに、さまざまな形式 (場合によってはそれ以上) の結果セットのコピーがメモリ内に少なくとも 2 つ存在します。

コード/ループにはガベージ コレクションの機会がなく、後で発生する可能性があります。

メモリのプロファイリングに役立つ apptrace などのツールをご覧ください。

于 2015-08-06T12:03:18.030 に答える
1

これをアプリ エンジン チームに報告したところ、これが実際に問題であることを確認したようです (カーソルの処理に問題があると思われます)。

于 2015-09-02T15:34:40.957 に答える