当前位置: 首页 > 知识库问答 >
问题:

我的谷歌应用程序引擎代码内存泄漏

厉钊
2023-03-14

我有以下代码试图在一个大表上循环(~100k行;~30GB)

def updateEmailsInLoop(cursor=None, stats={}):
    BATCH_SIZE=10
    try:
        rawEmails, next_cursor, more = RawEmailModel.query().fetch_page(BATCH_SIZE, start_cursor=cursor)
        for index, rawEmail in enumerate(rawEmails):
            stats = process_stats(rawEmail, stats)
        i = 0
        while more and next_cursor:
            rawEmails, next_cursor, more = RawEmailModel.query().fetch_page(BATCH_SIZE, start_cursor=next_cursor)
            for index, rawEmail in enumerate(rawEmails):
                stats = process_stats(rawEmail, stats)
            i = (i + 1) %100
            if i == 99:
                logging.info("foobar: Finished 100 more %s", str(stats))
        write_stats(stats)
    except DeadlineExceededError:
        logging.info("foobar: Deadline exceeded")
        for index, rawEmail in enumerate(rawEmails[index:], start=index):
            stats = process_stats(rawEmail, stats)
        if more and next_cursor:
            deferred.defer(updateEmailsInLoop, cursor = next_cursor, stats=stats, _queue="adminStats")

但是,我不断遇到以下错误:

处理此请求时,发现处理此请求的进程占用了太多内存,因此终止。这可能会导致应用程序的下一个请求使用新进程。如果经常看到此消息,则应用程序中可能存在内存泄漏。

...有时候......

在处理总共9个请求后,超过了128 MB的软私有内存限制,达到154 MB

我改变了我的代码,所以我总是在任何给定的时间只提取10个条目,所以我不明白为什么我的内存仍然不足?

共有1个答案

微生承业
2023-03-14

有3种方法可以完成此类工作(在数据存储中的一大组行上进行迭代):

  1. 处理1批x实体,并使用游标创建任务(推送队列)。
  2. 处理1批x实体,并用一点javascript对浏览器做出响应,该javascript显示进度和window.location到包含光标和当前进度的链接的更改。(>
  3. 使用map减少(它更难编码)(但可以应用于10M-1B行)

对于我需要的大多数应用程序,x通常在100-500之间。下面是我在1.5m-2m行的迭代中用来生成一些报告或更新数据库中的内容的代码。对于报告,我以csv格式保存一个包含所需信息的实体,最后读取所有实体,合并并删除它们。(这样做是为了生成150万行excel数据)(它是java,但应该很容易翻译成python):

 resp.getWriter().println("<html><head>");
 resp.getWriter().println(
                    "<script type='text/javascript'>function f(){window.location.href='/do/convert/" + this.getClass().getSimpleName() + "?cursor=" + cursorString + "&count="
                            + count + "';}</script>");
 resp.getWriter().println("</head><body onload='f()'>");
 resp.getWriter().println(
                    "<a href='/do/convert/" + this.getClass().getSimpleName() + "?cursor=" + cursorString + "&count=" + count + "'>Next page -->" + cursorString + " </a>");
 resp.getWriter().println("</body></html>");

如果你的进度很大,很乱,保存在实体中(一个或多个,取决于你在做什么)如果你正在做任务版本,我建议要么使用任务名称,要么让你的任务幂等(尤其是如果你在计算东西)。如果你计数的东西,我建议保存包含你正在计数的实体的密钥的实体,并在最后,计数那些。

 类似资料:
  • 我看到了这个Python问题:应用引擎延迟:跟踪内存泄漏 ...同样,我也遇到了这个可怕的错误: 在为总共384个请求提供服务后,超过了128 MB的软专用内存限制 ... 处理此请求后,发现处理此请求的进程占用了太多内存,因此被终止。这可能会导致应用程序的下一个请求使用新进程。如果经常看到此消息,则应用程序中可能存在内存泄漏。 根据另一个问题,可能是“实例类”太小,无法运行这个应用程序,但是在增

  • 我一直在努力了解如何在谷歌云上设置以下架构: 谷歌应用引擎收到HTTP请求

  • 我是谷歌应用引擎的新手。要使用Java App Engine,Google提供了两个选项:创建一个Maven项目,或者由Eclipse Google插件支持的非Maven项目。根据文档,Eclipse版本更容易。那么我应该继续日食吗?但是我看到了很多关于maven的帖子。有人能评论一下使用Maven的利弊吗。 谢谢

  • 它以GAE标准运行。更改日志权限后更新日志: 权限已更改:triage@appspot.gserviceaccount.com 应用程序引擎默认服务帐户 编辑器日志编写器所有者 有趣的是,到上周为止,它一直运行得很好。 当我试图访问该网站时,显示503个错误。2018-07-11 11:16:26.296 CDT GET 302 0 B 1 ms Chrome 67/144.188.128.2-[

  • 我正在看新的谷歌云数据存储,看起来很棒。但有件事我不明白。。。它应该替代谷歌应用引擎数据存储吗?我如何在GAE内部使用它?它们之间有什么区别? 我在Java有一个GAE应用程序,它使用3个实体,每个实体都有数千行,我需要经常做连接...