在检查 GO 中内存分配的性能时,我偶然发现了一件有趣的事情。
package main
import (
"fmt"
"time"
)
func main(){
const alloc int = 65536
now := time.Now()
loop := 50000
for i := 0; i<loop;i++{
sl := make([]byte, alloc)
i += len(sl) * 0
}
elpased := time.Since(now)
fmt.Printf("took %s to allocate %d bytes %d times", elpased, alloc, loop)
}
我在 Core-i7 2600 上运行这个程序,Go 版本 1.6 64 位(在 32 位上也有相同的结果)和 16GB RAM(在 WINDOWS 10 上)
因此,当 alloc 为 65536(正好是 64K)时,它会运行 30 秒(!!!)。
当 alloc 为 65535 时,大约需要 200 毫秒。
有人可以向我解释一下吗?
我在家里用我的核心 i7-920 @ 3.8GHZ 尝试了相同的代码,但没有显示相同的结果(两者都花费了大约 200 毫秒)。有人知道发生了什么事吗?
设置 GOGC=off 可以提高性能(降低到小于 100 毫秒)。为什么?
因为逃逸分析 https://github.com/golang/go/wiki/CompilerOptimizations#escape-analysis-and-inlining。当你构建时go build -gcflags -m
编译器打印任何逃逸到堆的分配。这实际上取决于你的机器和 GO 编译器版本,但是当编译器决定分配应该移动到堆时,这意味着两件事:
1.分配将花费更长的时间(因为在堆栈上“分配”只是1个CPU指令)
2. GC 稍后必须清理该内存 - 花费更多的 CPU 时间
对于我的机器,65536 字节的分配会转义到堆,而 65535 则不会。
这就是为什么1个字节将整个过程从200ms变成了30s。惊人的..
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)