为了账号安全,请及时绑定邮箱和手机立即绑定

Google App Engine Go 内存管理

Google App Engine Go 内存管理

Go
aluckdog 2021-06-08 17:51:43
我最近遇到了一个问题,App Engine 会终止我的 Go 实例,因为它说它内存不足。实例的内存限制设置为 128Mb。但是,我无法弄清楚所有内存分配在哪里。当我运行以下代码时:var s runtime.MemStatsruntime.ReadMemStats(&s)c.Debugf("allocated memory: %d", s.Alloc)它告诉我,当分配的内存达到大约 39-40Mb 时,我的应用程序因以下错误而终止:总共为 1 个请求提供服务后,超过了 135.082 MB 的软私有内存限制同样,当runtime.ReadMemStats(&s)指示我使用的是 20 Mb 时,App Engine 控制台会显示我的实例使用的是 92Mb。重做相同的请求,runtime.ReadMemStats(&s)仍然显示 20Mb,而 App Engine 控制台显示 119Mb。我已经禁用了appstats,仍然没有帮助。我的大部分内存都被内存缓存耗尽,我可以减少它以适应约束(或增加我的实例的内存限制),但我想知道所有内存都在哪里使用。如果有人可以对此有所了解,或者如何正确地分析 App Engine 上的内存使用情况,那将大有帮助。
查看完整描述

2 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

根据文档 Alloc字段显示已分配且仍在使用的字节。然而,在垃圾收集语言中,当内存被 GC 释放时,它不会立即返回给系统(它很快就会被再次请求,那么为什么要返回它呢?)。所以你真正需要监控的是Sys字段,它计算从系统获得的字节数。您可能对这篇文章感兴趣,其中有一些关于如何最小化内存使用的见解。

查看完整回答
反对 回复 2021-06-28
?
慕容708150

TA贡献1831条经验 获得超4个赞

设法在本地重现。

下面是一个示例应用程序,它在一个请求中分配一些整数,并在下一个请求中对它们进行垃圾收集:


// Package test implements a simple memory test for Google App Engine.

package test


import (

    "net/http"

    "runtime"


    "appengine"

)


var buffer []int64


func init() {

    http.HandleFunc("/", handler)

}


func handler(w http.ResponseWriter, r *http.Request) {

    var s runtime.MemStats

    c := appengine.NewContext(r)

    if len(buffer) == 0 {

        // Allocate 2^22 integers.

        runtime.ReadMemStats(&s)

        c.Debugf("Memory usage: %d bytes (%d system).", s.Alloc, s.Sys)

        buffer = make([]int64, 4*1024*1024)

        for i, _ := range buffer {

            buffer[i] = int64(i*i)

        }

        runtime.ReadMemStats(&s)

        c.Debugf("Memory usage increased to: %d bytes (%d system).", s.Alloc, s.Sys)

    } else {

        // Remove all references to the slice pointed to by buffer.

        // This should mark it for garbage collection.

        runtime.ReadMemStats(&s)

        c.Debugf("Memory usage: %d bytes (%d system).", s.Alloc, s.Sys)

        buffer = nil

        runtime.GC()

        runtime.ReadMemStats(&s)

        c.Debugf("After GC event: %d bytes (%d system).", s.Alloc, s.Sys)

    }

    w.WriteHeader(http.StatusTeapot)

}

使用开发服务器运行时:


$ ./go_appengine/dev_appserver.py test


2013/09/16 12:28:28 DEBUG: Memory usage: 833096 bytes (272681032 system).

2013/09/16 12:28:28 DEBUG: Memory usage increased to: 34335216 bytes (308332616 system).

INFO     2013-09-16 12:28:28,884 module.py:593] default: "GET / HTTP/1.1" 418 -

2013/09/16 12:28:29 DEBUG: Memory usage: 34345896 bytes (308332616 system).

2013/09/16 12:28:29 DEBUG: After GC event: 781504 bytes (308332616 system).

INFO     2013-09-16 12:28:29,560 module.py:593] default: "GET / HTTP/1.1" 418 -

2013/09/16 12:28:30 DEBUG: Memory usage: 791616 bytes (308332616 system).

2013/09/16 12:28:30 DEBUG: Memory usage increased to: 34337392 bytes (308332616 system).

INFO     2013-09-16 12:28:30,276 module.py:593] default: "GET / HTTP/1.1" 418 -

2013/09/16 12:28:36 DEBUG: Memory usage: 34347536 bytes (308332616 system).

2013/09/16 12:28:36 DEBUG: After GC event: 783632 bytes (308332616 system).

INFO     2013-09-16 12:28:36,224 module.py:593] default: "GET / HTTP/1.1" 418 -

看来内存分配和垃圾收集工作正常。但是,查看ps输出,似乎释放内存并没有减少进程的虚拟内存使用:


$ ps axo command,vsize,rss | ag go_app

/usr/bin/python2.7 ./go_app 381248 56608

$ ps axo command,vsize,rss | ag go_app

/usr/bin/python2.7 ./go_app 676324 57652

$ ps axo command,vsize,rss | ag go_app

/usr/bin/python2.7 ./go_app 750056 57856

$ ps axo command,vsize,rss | ag go_app

/usr/bin/python2.7 ./go_app 750056 57856

似乎运行底层 Go 实例的 Python 进程不断增加其虚拟内存,但它从未被释放。在生产服务器上似乎也发生了类似的事情:实例运行时报告的分配内存与内核报告的已使用内存不同。

查看完整回答
反对 回复 2021-06-28
  • 2 回答
  • 0 关注
  • 264 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信