【问题标题】:NDB not clearing memory during a long requestNDB 在长时间请求期间未清除内存
【发布时间】:2012-08-23 15:35:16
【问题描述】:

我目前正在将长时间运行的作业卸载到 TaskQueue 以计算数据存储区中 NDB 实体之间的连接。

基本上,此队列处理多个实体键列表,这些实体键将通过GetConnectedNodes 节点中的node_in_connected_nodes 函数与另一个query 相关联:

class GetConnectedNodes(object):
"""Class for getting the connected nodes from a list of nodes in a paged way"""
def __init__(self, list, query):
    # super(GetConnectedNodes, self).__init__()
    self.nodes = [ndb.model.Key('Node','%s' % x) for x in list]
    self.cursor = 0
    self.MAX_QUERY = 100
    # logging.info('Max query - %d' % self.MAX_QUERY)
    self.max_connections = len(list)
    self.connections = deque()
    self.query=query

def node_in_connected_nodes(self):
    """Checks if a node exists in the connected nodes of the next node in the 
       node list.
       Will return False if it doesn't, or the list of evidences for the connection
       if it does.
       """
    while self.cursor < self.max_connections:
        if len(self.connections) == 0:
            end = self.MAX_QUERY
            if self.max_connections - self.cursor < self.MAX_QUERY:
                end = self.max_connections - self.cursor
            self.connections.clear()
            self.connections = deque(ndb.model.get_multi_async(self.nodes[self.cursor:self.cursor+end]))

        connection = self.connections.popleft()
        connection_nodes = connection.get_result().connections

        if self.query in connection_nodes:
            connection_sources = connection.get_result().sources
            # yields (current node index in the list, sources)
            yield (self.cursor, connection_sources[connection_nodes.index(self.query)])
        self.cursor += 1

这里Node 有一个重复属性connections,其中包含一个带有其他Node 键ID 的数组,以及一个与给定连接匹配的sources 数组。

生成的结果存储在 blobstore 中。

现在我遇到的问题是,在连接函数的迭代之后,内存没有以某种方式被清除。以下日志显示了 AppEngine 在创建新的 GetConnectedNodes 实例之前使用的内存:

I 2012-08-23 16:58:01.643 Prioritizing HGNC:4839 - mem 32
I 2012-08-23 16:59:21.819 Prioritizing HGNC:3003 - mem 380
I 2012-08-23 17:00:00.918 Prioritizing HGNC:8932 - mem 468
I 2012-08-23 17:00:01.424 Prioritizing HGNC:24771 - mem 435
I 2012-08-23 17:00:20.334 Prioritizing HGNC:9300 - mem 417
I 2012-08-23 17:00:48.476 Prioritizing HGNC:10545 - mem 447
I 2012-08-23 17:01:01.489 Prioritizing HGNC:12775 - mem 485
I 2012-08-23 17:01:46.084 Prioritizing HGNC:2001 - mem 564
C 2012-08-23 17:02:18.028 Exceeded soft private memory limit with 628.609 MB after servicing 1 requests total

除了一些波动之外,内存一直在增加,即使之前的值都没有被访问。我发现很难调试这个或弄清楚我是否在某个地方有内存泄漏,但我似乎已经将它追溯到那个类。将不胜感激。

【问题讨论】:

  • 您介意分享一下您是如何记录您的内存使用情况的吗?

标签: python google-app-engine memory-leaks task-queue app-engine-ndb


【解决方案1】:

我们也遇到过类似的问题(请求运行时间很长)。 我们通过关闭默认的 ndb 缓存解决了这些问题。 你可以阅读更多关于它here

【讨论】:

  • 啊,我错过了这是一个长期运行的请求。对不起。事实上,NDB 的上下文缓存不断收集更多的对象。如果它是一个特定的模型类,你可以把 _use_cache = False 放在类体中,以避免缓存它。或者您可以在循环顶部调用 ndb.get_context().clear_cache()。
  • 绕过上下文缓存将实例保持在限制范围内。谢谢您的帮助!我也在编辑这个问题,以便更多人以后可以找到它。
  • 很高兴能帮到你 m8 ;)
【解决方案2】:

在我们的例子中,这是由 AppEngine Appstats 启用引起的。

禁用后,内存消耗恢复正常。

【讨论】:

    【解决方案3】:

    您可以在每个请求开始时调用 gc.collect()。

    【讨论】:

    • 调用 gc.collect() 无效。更令人不安的是,如果我一次使用一个实体而不是列表调用处理程序,则实例内存会不断增加,直到它也被终止。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多