-
Notifications
You must be signed in to change notification settings - Fork 7
/
bitmap_test.go
130 lines (120 loc) · 2.91 KB
/
bitmap_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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) })
}
}