mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: add packed bitmap summaries
This change adds the concept of summaries and of summarizing a set of pallocBits, a core concept in the new page allocator. These summaries are really just three integers packed into a uint64. This change also adds tests and a benchmark for generating these summaries. Updates #35112. Change-Id: I69686316086c820c792b7a54235859c2105e5fee Reviewed-on: https://go-review.googlesource.com/c/go/+/190621 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
b3a361337c
commit
cec01395c5
4 changed files with 293 additions and 0 deletions
|
|
@ -5,6 +5,8 @@
|
|||
package runtime_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
. "runtime"
|
||||
"testing"
|
||||
)
|
||||
|
|
@ -95,6 +97,130 @@ func invertPallocBits(b *PallocBits) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensures two packed summaries are identical, and reports a detailed description
|
||||
// of the difference if they're not.
|
||||
func checkPallocSum(t *testing.T, got, want PallocSum) {
|
||||
if got.Start() != want.Start() {
|
||||
t.Errorf("inconsistent start: got %d, want %d", got.Start(), want.Start())
|
||||
}
|
||||
if got.Max() != want.Max() {
|
||||
t.Errorf("inconsistent max: got %d, want %d", got.Max(), want.Max())
|
||||
}
|
||||
if got.End() != want.End() {
|
||||
t.Errorf("inconsistent end: got %d, want %d", got.End(), want.End())
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures computing bit summaries works as expected by generating random
|
||||
// bitmaps and checking against a reference implementation.
|
||||
func TestPallocBitsSummarizeRandom(t *testing.T) {
|
||||
b := new(PallocBits)
|
||||
for i := 0; i < 1000; i++ {
|
||||
// Randomize bitmap.
|
||||
for i := range b {
|
||||
b[i] = rand.Uint64()
|
||||
}
|
||||
// Check summary against reference implementation.
|
||||
checkPallocSum(t, b.Summarize(), SummarizeSlow(b))
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures computing bit summaries works as expected.
|
||||
func TestPallocBitsSummarize(t *testing.T) {
|
||||
var emptySum = PackPallocSum(PallocChunkPages, PallocChunkPages, PallocChunkPages)
|
||||
type test struct {
|
||||
free []BitRange // Ranges of free (zero) bits.
|
||||
hits []PallocSum
|
||||
}
|
||||
tests := make(map[string]test)
|
||||
tests["NoneFree"] = test{
|
||||
free: []BitRange{},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(0, 0, 0),
|
||||
},
|
||||
}
|
||||
tests["OnlyStart"] = test{
|
||||
free: []BitRange{{0, 10}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(10, 10, 0),
|
||||
},
|
||||
}
|
||||
tests["OnlyEnd"] = test{
|
||||
free: []BitRange{{PallocChunkPages - 40, 40}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(0, 40, 40),
|
||||
},
|
||||
}
|
||||
tests["StartAndEnd"] = test{
|
||||
free: []BitRange{{0, 11}, {PallocChunkPages - 23, 23}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(11, 23, 23),
|
||||
},
|
||||
}
|
||||
tests["StartMaxEnd"] = test{
|
||||
free: []BitRange{{0, 4}, {50, 100}, {PallocChunkPages - 4, 4}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(4, 100, 4),
|
||||
},
|
||||
}
|
||||
tests["OnlyMax"] = test{
|
||||
free: []BitRange{{1, 20}, {35, 241}, {PallocChunkPages - 50, 30}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(0, 241, 0),
|
||||
},
|
||||
}
|
||||
tests["MultiMax"] = test{
|
||||
free: []BitRange{{35, 2}, {40, 5}, {100, 5}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(0, 5, 0),
|
||||
},
|
||||
}
|
||||
tests["One"] = test{
|
||||
free: []BitRange{{2, 1}},
|
||||
hits: []PallocSum{
|
||||
PackPallocSum(0, 1, 0),
|
||||
},
|
||||
}
|
||||
tests["AllFree"] = test{
|
||||
free: []BitRange{{0, PallocChunkPages}},
|
||||
hits: []PallocSum{
|
||||
emptySum,
|
||||
},
|
||||
}
|
||||
for name, v := range tests {
|
||||
v := v
|
||||
t.Run(name, func(t *testing.T) {
|
||||
b := makePallocBits(v.free)
|
||||
// In the PallocBits we create 1's represent free spots, but in our actual
|
||||
// PallocBits 1 means not free, so invert.
|
||||
invertPallocBits(b)
|
||||
for _, h := range v.hits {
|
||||
checkPallocSum(t, b.Summarize(), h)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks how quickly we can summarize a PallocBits.
|
||||
func BenchmarkPallocBitsSummarize(b *testing.B) {
|
||||
buf0 := new(PallocBits)
|
||||
buf1 := new(PallocBits)
|
||||
for i := 0; i < len(buf1); i++ {
|
||||
buf1[i] = ^uint64(0)
|
||||
}
|
||||
bufa := new(PallocBits)
|
||||
for i := 0; i < len(bufa); i++ {
|
||||
bufa[i] = 0xaa
|
||||
}
|
||||
for _, buf := range []*PallocBits{buf0, buf1, bufa} {
|
||||
b.Run(fmt.Sprintf("Unpacked%02X", buf[0]), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Summarize()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures page allocation works.
|
||||
func TestPallocBitsAlloc(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue