131 lines
2.9 KiB
Go
131 lines
2.9 KiB
Go
|
package memsize
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math/rand"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestBitmapBlock(t *testing.T) {
|
||
|
marks := map[uintptr]bool{
|
||
|
10: true,
|
||
|
13: true,
|
||
|
44: true,
|
||
|
128: true,
|
||
|
129: true,
|
||
|
256: true,
|
||
|
700: true,
|
||
|
}
|
||
|
var b bmBlock
|
||
|
for i := range marks {
|
||
|
b.mark(i)
|
||
|
}
|
||
|
for i := uintptr(0); i < bmBlockRange; i++ {
|
||
|
if b.isMarked(i) && !marks[i] {
|
||
|
t.Fatalf("wrong mark at %d", i)
|
||
|
}
|
||
|
}
|
||
|
if count := b.count(0, bmBlockRange-1); count != len(marks) {
|
||
|
t.Fatalf("wrong onesCount: got %d, want %d", count, len(marks))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBitmapBlockCount(t *testing.T) {
|
||
|
var b bmBlock
|
||
|
// Mark addresses (90,250)
|
||
|
for i := 90; i < 250; i++ {
|
||
|
b.mark(uintptr(i))
|
||
|
}
|
||
|
// Check counts.
|
||
|
tests := []struct {
|
||
|
start, end uintptr
|
||
|
want int
|
||
|
}{
|
||
|
{start: 0, end: 0, want: 0},
|
||
|
{start: 0, end: 10, want: 0},
|
||
|
{start: 0, end: 250, want: 160},
|
||
|
{start: 0, end: 240, want: 150},
|
||
|
{start: 0, end: bmBlockRange - 1, want: 160},
|
||
|
{start: 100, end: bmBlockRange - 1, want: 150},
|
||
|
{start: 100, end: 110, want: 10},
|
||
|
{start: 100, end: 250, want: 150},
|
||
|
{start: 100, end: 211, want: 111},
|
||
|
{start: 111, end: 211, want: 100},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%d-%d", test.start, test.end), func(t *testing.T) {
|
||
|
if c := b.count(test.start, test.end); c != test.want {
|
||
|
t.Errorf("wrong onesCountRange(%d, %d): got %d, want %d", test.start, test.end, c, test.want)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestBitmapMarkRange(t *testing.T) {
|
||
|
N := 1000
|
||
|
|
||
|
// Generate random non-overlapping mark ranges.
|
||
|
var (
|
||
|
r = rand.New(rand.NewSource(312321312))
|
||
|
bm = newBitmap()
|
||
|
ranges = make(map[uintptr]uintptr)
|
||
|
addr uintptr
|
||
|
total uintptr // number of bytes marked
|
||
|
)
|
||
|
for i := 0; i < N; i++ {
|
||
|
addr += uintptr(r.Intn(bmBlockRange))
|
||
|
len := uintptr(r.Intn(40))
|
||
|
total += len
|
||
|
ranges[addr] = len
|
||
|
bm.markRange(addr, len)
|
||
|
}
|
||
|
|
||
|
// Check all marks are set.
|
||
|
for start, len := range ranges {
|
||
|
for i := uintptr(0); i < len; i++ {
|
||
|
if !bm.isMarked(start + i) {
|
||
|
t.Fatalf("not marked at %d", start)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check total number of bits is reported correctly.
|
||
|
if c := bm.countRange(0, addr+ranges[addr]); c != total {
|
||
|
t.Errorf("countRange(0, %d) returned %d, want %d", addr, c, total)
|
||
|
}
|
||
|
|
||
|
// Probe random addresses.
|
||
|
for i := 0; i < N; i++ {
|
||
|
addr := uintptr(r.Uint64())
|
||
|
marked := false
|
||
|
for start, len := range ranges {
|
||
|
if addr >= start && addr < start+len {
|
||
|
marked = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if bm.isMarked(addr) && !marked {
|
||
|
t.Fatalf("extra mark at %d", addr)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkBitmapMarkRange(b *testing.B) {
|
||
|
var addrs [2048]uintptr
|
||
|
r := rand.New(rand.NewSource(423098209802))
|
||
|
for i := range addrs {
|
||
|
addrs[i] = uintptr(r.Uint64())
|
||
|
}
|
||
|
|
||
|
doit := func(b *testing.B, rlen int) {
|
||
|
bm := newBitmap()
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
addr := addrs[i%len(addrs)]
|
||
|
bm.markRange(addr, uintptr(rlen))
|
||
|
}
|
||
|
}
|
||
|
for rlen := 1; rlen <= 4096; rlen *= 8 {
|
||
|
b.Run(fmt.Sprintf("%d", rlen), func(b *testing.B) { doit(b, rlen) })
|
||
|
}
|
||
|
}
|