mirror of
https://github.com/golang/go.git
synced 2026-06-28 03:40:37 +00:00
runtime: add microbenchmarks for sizespecializedmalloc
This change adds code to generate benchmarks for calling mallocgc both through the generated calls and directly, for use when benchmarking sizespecializedmalloc changes. For #79286 Change-Id: I0490fd8d72721cf25960086e82e55da96a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/775980 Reviewed-by: Michael Matloob <matloob@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
9936a78b78
commit
15129eb73b
4 changed files with 1596 additions and 0 deletions
|
|
@ -63,6 +63,12 @@ func main() {
|
|||
if err := os.WriteFile(tablefile, mustFormat(generateTable(sizeToSizeClass)), 0666); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
benchmarkFile := "../malloc_bench_generated_test.go"
|
||||
if err := os.WriteFile(benchmarkFile, mustFormat(append(inline(benchmarkConfig(classes, sizeToSizeClass)), []byte(generateTopBenchmark(classes, sizeToSizeClass))...)), 0666); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// withLineNumbers returns b with line numbers added to help debugging.
|
||||
|
|
@ -659,3 +665,70 @@ var mallocNoScanTable = [513]func(size uintptr, typ *_type, needzero bool) unsaf
|
|||
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// benchmarkConfig produces an inlining config to stamp out microbenchmarks.
|
||||
func benchmarkConfig(classes []class, sizeToSizeClass []uint8) generatorConfig {
|
||||
config := generatorConfig{file: "../malloc_stubs_test.go"}
|
||||
|
||||
// Only generate specialized functions for sizes that don't have
|
||||
// a header on 64-bit platforms. (They may have a header on 32-bit, but
|
||||
// we will fall back to the non-specialized versions in that case)
|
||||
scMax := sizeToSizeClass[smallScanNoHeaderMax]
|
||||
|
||||
str := fmt.Sprint
|
||||
|
||||
for sc := uint8(1); sc <= scMax; sc++ {
|
||||
elemsize := classes[sc].size
|
||||
config.specs = append(config.specs, spec{
|
||||
templateFunc: "benchmarkStub",
|
||||
name: fmt.Sprintf("benchmarkMallocgcNoscan%d", elemsize),
|
||||
ops: []op{
|
||||
{subBasicLit, "size_", str(elemsize)},
|
||||
{foldCondition, "noscan_", str(true)},
|
||||
},
|
||||
})
|
||||
config.specs = append(config.specs, spec{
|
||||
templateFunc: "benchmarkStub",
|
||||
name: fmt.Sprintf("benchmarkMallocgcScan%d", elemsize),
|
||||
ops: []op{
|
||||
{subBasicLit, "size_", str(elemsize)},
|
||||
{foldCondition, "noscan_", str(false)},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for size := 1; size < tinySize; size++ {
|
||||
config.specs = append(config.specs, spec{
|
||||
templateFunc: "benchmarkStubTiny",
|
||||
name: fmt.Sprintf("benchmarkMallocgcTiny%d", size),
|
||||
ops: []op{{subBasicLit, "size_", str(size)}, {foldCondition, "noscan_", str(true)}},
|
||||
})
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func generateTopBenchmark(classes []class, sizeToSizeClass []uint8) string {
|
||||
scMax := sizeToSizeClass[smallScanNoHeaderMax]
|
||||
bench := `func BenchmarkMallocgc(b *testing.B) {
|
||||
b.Run("scan=noscan", func(b *testing.B) {
|
||||
`
|
||||
for size := 1; size < tinySize; size++ {
|
||||
bench += fmt.Sprintf(`b.Run("size=%d", benchmarkMallocgcTiny%d)`, size, size) + "\n"
|
||||
}
|
||||
for sc := uint8(2); sc <= scMax; sc++ {
|
||||
elemsize := classes[sc].size
|
||||
bench += fmt.Sprintf(`b.Run("size=%d", benchmarkMallocgcNoscan%d)`, elemsize, elemsize) + "\n"
|
||||
}
|
||||
bench += `})
|
||||
b.Run("scan=scan", func(b *testing.B) {
|
||||
`
|
||||
for sc := uint8(1); sc <= scMax; sc++ {
|
||||
elemsize := classes[sc].size
|
||||
bench += fmt.Sprintf(`b.Run("size=%d", benchmarkMallocgcScan%d)`, elemsize, elemsize) + "\n"
|
||||
}
|
||||
bench += `})
|
||||
}`
|
||||
|
||||
return bench
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2114,3 +2114,7 @@ func GetScanAlloc() uintptr {
|
|||
c := getMCache(getg().m)
|
||||
return c.scanAlloc
|
||||
}
|
||||
|
||||
func MallocGC(size uintptr, typ *abi.Type, needzero bool) unsafe.Pointer {
|
||||
return mallocgc(size, typ, needzero)
|
||||
}
|
||||
|
|
|
|||
1460
src/runtime/malloc_bench_generated_test.go
Normal file
1460
src/runtime/malloc_bench_generated_test.go
Normal file
File diff suppressed because it is too large
Load diff
59
src/runtime/malloc_stubs_test.go
Normal file
59
src/runtime/malloc_stubs_test.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2026 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"internal/abi"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const size_ = 0
|
||||
|
||||
func benchmarkStubTiny(b *testing.B) {
|
||||
const size = size_
|
||||
type s struct {
|
||||
v [size]byte
|
||||
}
|
||||
b.Run("kind=new", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
runtime.Escape(new(s))
|
||||
}
|
||||
})
|
||||
typ := abi.TypeOf(s{})
|
||||
b.Run("kind=mallocgc", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
runtime.Escape(runtime.MallocGC(size, typ, false))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const noscan_ = false
|
||||
|
||||
func benchmarkStub(b *testing.B) {
|
||||
const size = size_
|
||||
b.Run("kind=new", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
if noscan_ {
|
||||
runtime.Escape(new(struct{ v [size / 8]uint64 }))
|
||||
}
|
||||
if !noscan_ {
|
||||
runtime.Escape(new(struct{ v [size / 8]*uint64 }))
|
||||
}
|
||||
}
|
||||
})
|
||||
var typ *abi.Type
|
||||
if noscan_ {
|
||||
typ = abi.TypeOf(struct{ v [size / 8]uint64 }{})
|
||||
}
|
||||
if !noscan_ {
|
||||
typ = abi.TypeOf(struct{ v [size / 8]*uint64 }{})
|
||||
}
|
||||
b.Run("kind=mallocgc", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
runtime.Escape(runtime.MallocGC(size, typ, true))
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue