目的
値のサイズが、配置されるメモリ領域(ヒープ or スタック)に影響を及ぼす可能性があることを理解する。
環境
$ go version
go version go1.23.2 linux/amd64
検証
(1) 値のサイズが小さく、スタックに置かれるパターン
package main
const size = 64 * 1024
func main() {
_ = make([]byte, size)
}
package main
import "testing"
func Benchmark(b *testing.B) {
for i := 0; i < b.N; i++ {
main()
}
}
$ go build -gcflags "-m=2" .
# gopractice
./main.go:5:6: can inline main with cost 4 as: func() { _ = make([]byte, 65536) }
./main.go:6:10: make([]byte, 65536) does not escape
$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: gopractice
cpu: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
Benchmark-2 1000000000 0.3695 ns/op 0 B/op 0 allocs/op
PASS
ok gopractice 0.418s
$ go build -o main_binary main.go
$ objdump -d main_binary > objdump.txt
0000000000466be0 <main.main>:
466be0: c3 ret
466be1: cc int3
466be2: cc int3
466be3: cc int3
466be4: cc int3
466be5: cc int3
466be6: cc int3
466be7: cc int3
466be8: cc int3
466be9: cc int3
466bea: cc int3
466beb: cc int3
466bec: cc int3
466bed: cc int3
466bee: cc int3
466bef: cc int3
466bf0: cc int3
466bf1: cc int3
466bf2: cc int3
466bf3: cc int3
466bf4: cc int3
466bf5: cc int3
466bf6: cc int3
466bf7: cc int3
466bf8: cc int3
466bf9: cc int3
466bfa: cc int3
466bfb: cc int3
466bfc: cc int3
466bfd: cc int3
466bfe: cc int3
466bff: cc int3
(2) 値のサイズが大きく、ヒープに置かれるパターン
package main
const size = 64*1024 + 1
func main() {
_ = make([]byte, size)
}
package main
import "testing"
func Benchmark(b *testing.B) {
for i := 0; i < b.N; i++ {
main()
}
}
$ go build -gcflags "-m=2" .
# gopractice
./main.go:5:6: can inline main with cost 4 as: func() { _ = make([]byte, 65537) }
./main.go:6:10: make([]byte, 65537) escapes to heap:
./main.go:6:10: flow: {heap} = &{storage for make([]byte, 65537)}:
./main.go:6:10: from make([]byte, 65537) (too large for stack) at ./main.go:6:10
./main.go:6:10: make([]byte, 65537) escapes to heap
$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: gopractice
cpu: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
Benchmark-2 79288 15874 ns/op 73728 B/op 1 allocs/op
PASS
ok gopractice 1.415s
$ go build -o main_binary main.go
$ objdump -d main_binary > objdump.txt
0000000000466be0 <main.main>:
466be0: 49 3b 66 10 cmp 0x10(%r14),%rsp
466be4: 76 25 jbe 466c0b <main.main+0x2b>
466be6: 55 push %rbp
466be7: 48 89 e5 mov %rsp,%rbp
466bea: 48 83 ec 18 sub $0x18,%rsp
466bee: 48 8d 05 4b 56 00 00 lea 0x564b(%rip),%rax # 46c240 <type:*+0x5240>
466bf5: bb 01 00 01 00 mov $0x10001,%ebx
466bfa: 48 89 d9 mov %rbx,%rcx
466bfd: 0f 1f 00 nopl (%rax)
466c00: e8 5b 79 ff ff call 45e560 <runtime.makeslice>
466c05: 48 83 c4 18 add $0x18,%rsp
466c09: 5d pop %rbp
466c0a: c3 ret
466c0b: e8 10 b1 ff ff call 461d20 <runtime.morestack_noctxt.abi0>
466c10: eb ce jmp 466be0 <main.main>
466c12: cc int3
466c13: cc int3
466c14: cc int3
466c15: cc int3
466c16: cc int3
466c17: cc int3
466c18: cc int3
466c19: cc int3
466c1a: cc int3
466c1b: cc int3
466c1c: cc int3
466c1d: cc int3
466c1e: cc int3
466c1f: cc int3
参考