Google App Engine 数据库查询内存使用情况

Google App Engine DB Query Memory Usage

当我 运行 查询一大组小对象(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() 不记录任何统计信息。

有人知道会发生什么吗?或者关于如何 debug/profile 这个的任何指示?

更新 1:我在生产代码上打开了 gc.set_debug(gc.DEBUG_STATS),我看到垃圾收集器被定期调用,所以它 试图收集垃圾。当我在循环结束时(也是请求结束时)调用 gc.collect() 时;它 returns 0,但没有帮助。

更新 2:我做了一些 hacking 让孔雀鱼在 dev_appserver 上工作,这似乎表明,在明确 gc.collect() 之后循环结束,大部分内存被'dict of google.appengine.datastore.entity_pb.Property'.

消耗了

每个模型实体都有一些开销。

您查询 returns 个对象作为初学者的 Protobuf。

因此您将为结果集生成一系列批处理的 protobuf。

然后解码。每个解码的实体都包含 属性 个名称以及每个实体的数据。您有 15K 个实体。例如,你的 属性 名字有多大。

因此您在内存中至少有两个不同形式的结果集副本(可能更多),不包括您对模型实例所做的任何其他操作 class。

您 code/loop 没有机会进行垃圾回收,can/will 稍后会发生。

看看 apptrace 之类的工具来帮助内存分析。

我已将此报告给应用引擎团队,他们似乎确认这确实是一个问题(怀疑与游标的处理有关)。