我写了一个简单的http golang webserver来测试Go垃圾收集(释放无法访问的指针的内存),但是在strees测试中,我知道它消耗了过多的ram。
根据一些question/answers,我发现Golang会自动进行垃圾收集,管理额外的内存本身并且不会立即将内存恢复到操作系统。一些结果:
网络服务器在大约5分钟后释放内存。
网络服务器使用ram直到达到特定级别并请求更多连接没有获得更多内存(在我的情况下约为4GB)
消耗4GB的ram并不酷!所以我在我的代码中添加了一个Goroutine,它将额外的内存带回了操作系统。
代码:
type t struct{
a []string
b map[string]string
}
var x t = t{
a: []string{"1","2"},
b: make(map[string]string),
}
func handler(w http.ResponseWriter, r *http.Request) {
x := &t{}
fmt.Fprintf(w, "pong", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/ping", handler)
go func(){
for {
time.Sleep(10 * time.Second)
fmt.Println("Free up memory...")
debug.FreeOSMemory()
}
}()
log.Fatal(http.ListenAndServe(":8080", nil))
}
对于压力测试,我使用Apache Bench:
ab -c 100 -n 400000 http://127.0.0.1:8080/ping
我连续跑了10次以上的命令来检查ram的使用情况。 它的效果非常好,但问题是,是否有任何标准方式可以更好地释放内存!?
我知道在某些情况下,Go管理内存本身而不是重复释放并从操作系统中获取内存是好的,但在我的情况下,5分钟的延迟对释放内存非常重要。
答案 0 :(得分:4)
您可能希望从runtime/debug
但你可能不应该这样做。请尝试针对您的特定应用程序和用法调整GC(可能使用SetGCPercent)。很可能经常使用FreeOSMemory
降低性能,因此请务必进行基准测试。
请注意,垃圾收集实现在Go的最新版本中有所改进,并且在各种Go实现中有所不同(例如在GCC Go中)。
不要混淆RAM使用(RAM由您的操作系统内核管理,而不是由您的Go流程管理),virtual memory,virtual address space。阅读RSS,demand paging,thrashing。
有关垃圾收集技术的概述,请阅读The GC Handbook。
为了更好地了解操作系统,请阅读Operating Systems: Three Easy Pieces