3 回答
TA贡献1757条经验 获得超7个赞
设置 GOGC=off 提高了性能(降低到小于 100 毫秒)。为什么?因为逃逸分析。当您使用go build -gcflags -m
编译器构建时,会打印任何逃逸到堆的分配。这实际上取决于您的机器和 GO 编译器版本,但是当编译器决定分配应该移到堆时,这意味着两件事:1. 分配将花费更长的时间(因为堆栈上的“分配”只是 1 个 cpu 指令)2. GC 稍后将不得不清理该内存 - 为我的机器花费更多的 CPU 时间,65536 字节的分配转义到堆,而 65535 则不会。这就是为什么 1 个字节将整个过程从 200 毫秒更改为 30 秒的原因。惊人..
TA贡献1806条经验 获得超8个赞
注意/2021 年更新:正如Tapir Liui在Go101中用这条推文指出的那样:
从 Go 1.17 开始,如果编译器证明它们仅在当前 goroutine 中使用,并且Go 运行时将在堆栈上分配slice 的元素:xN <= 64KB
var x = make([]byte, N)
如果编译器证明它仅用于当前 goroutine并且 Go 运行时将在堆栈上分配数组 :yN <= 10MB
var y [N]byte
那么如何分配的(的元素)片,其尺寸大于64KB上堆叠更大但不大于10MB(和切片仅在一个够程中使用)?
只需使用以下方式:
var y [N]byte
var x = y[:]
考虑到堆栈分配比堆分配快,这将对您的测试产生直接影响,因为alloc等于 65536 或更多。
貘补充说:
事实上,我们可以在堆栈上分配具有任意总和元素大小的切片。
const N = 500 * 1024 * 1024 // 500M
var v byte = 123
func createSlice() byte {
var s = []byte{N: 0}
for i := range s { s[i] = v }
return s[v]
}
将 500 更改为 512 会使程序崩溃。
TA贡献1776条经验 获得超12个赞
原因很简单。
const alloc int = 65535
0x0000 00000 (example.go:8) TEXT "".main(SB), ABIInternal, $65784-0
const alloc int = 65536
0x0000 00000 (example.go:8) TEXT "".main(SB), ABIInternal, $248-0
不同之处在于切片的创建位置。
- 3 回答
- 0 关注
- 220 浏览
添加回答
举报