github.com/fjl/memsize@v0.0.2/bitmap_test.go (about)

     1  package memsize
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"testing"
     7  )
     8  
     9  func TestBitmapBlock(t *testing.T) {
    10  	marks := map[uintptr]bool{
    11  		10:  true,
    12  		13:  true,
    13  		44:  true,
    14  		128: true,
    15  		129: true,
    16  		256: true,
    17  		700: true,
    18  	}
    19  	var b bmBlock
    20  	for i := range marks {
    21  		b.mark(i)
    22  	}
    23  	for i := uintptr(0); i < bmBlockRange; i++ {
    24  		if b.isMarked(i) && !marks[i] {
    25  			t.Fatalf("wrong mark at %d", i)
    26  		}
    27  	}
    28  	if count := b.count(0, bmBlockRange-1); count != len(marks) {
    29  		t.Fatalf("wrong onesCount: got %d, want %d", count, len(marks))
    30  	}
    31  }
    32  
    33  func TestBitmapBlockCount(t *testing.T) {
    34  	var b bmBlock
    35  	// Mark addresses (90,250)
    36  	for i := 90; i < 250; i++ {
    37  		b.mark(uintptr(i))
    38  	}
    39  	// Check counts.
    40  	tests := []struct {
    41  		start, end uintptr
    42  		want       int
    43  	}{
    44  		{start: 0, end: 0, want: 0},
    45  		{start: 0, end: 10, want: 0},
    46  		{start: 0, end: 250, want: 160},
    47  		{start: 0, end: 240, want: 150},
    48  		{start: 0, end: bmBlockRange - 1, want: 160},
    49  		{start: 100, end: bmBlockRange - 1, want: 150},
    50  		{start: 100, end: 110, want: 10},
    51  		{start: 100, end: 250, want: 150},
    52  		{start: 100, end: 211, want: 111},
    53  		{start: 111, end: 211, want: 100},
    54  	}
    55  	for _, test := range tests {
    56  		t.Run(fmt.Sprintf("%d-%d", test.start, test.end), func(t *testing.T) {
    57  			if c := b.count(test.start, test.end); c != test.want {
    58  				t.Errorf("wrong onesCountRange(%d, %d): got %d, want %d", test.start, test.end, c, test.want)
    59  			}
    60  		})
    61  	}
    62  }
    63  
    64  func TestBitmapMarkRange(t *testing.T) {
    65  	N := 1000
    66  
    67  	// Generate random non-overlapping mark ranges.
    68  	var (
    69  		r      = rand.New(rand.NewSource(312321312))
    70  		bm     = newBitmap()
    71  		ranges = make(map[uintptr]uintptr)
    72  		addr   uintptr
    73  		total  uintptr // number of bytes marked
    74  	)
    75  	for i := 0; i < N; i++ {
    76  		addr += uintptr(r.Intn(bmBlockRange))
    77  		len := uintptr(r.Intn(40))
    78  		total += len
    79  		ranges[addr] = len
    80  		bm.markRange(addr, len)
    81  	}
    82  
    83  	// Check all marks are set.
    84  	for start, len := range ranges {
    85  		for i := uintptr(0); i < len; i++ {
    86  			if !bm.isMarked(start + i) {
    87  				t.Fatalf("not marked at %d", start)
    88  			}
    89  		}
    90  	}
    91  
    92  	// Check total number of bits is reported correctly.
    93  	if c := bm.countRange(0, addr+ranges[addr]); c != total {
    94  		t.Errorf("countRange(0, %d) returned %d, want %d", addr, c, total)
    95  	}
    96  
    97  	// Probe random addresses.
    98  	for i := 0; i < N; i++ {
    99  		addr := uintptr(r.Uint64())
   100  		marked := false
   101  		for start, len := range ranges {
   102  			if addr >= start && addr < start+len {
   103  				marked = true
   104  				break
   105  			}
   106  		}
   107  		if bm.isMarked(addr) && !marked {
   108  			t.Fatalf("extra mark at %d", addr)
   109  		}
   110  	}
   111  }
   112  
   113  func BenchmarkBitmapMarkRange(b *testing.B) {
   114  	var addrs [2048]uintptr
   115  	r := rand.New(rand.NewSource(423098209802))
   116  	for i := range addrs {
   117  		addrs[i] = uintptr(r.Uint64())
   118  	}
   119  
   120  	doit := func(b *testing.B, rlen int) {
   121  		bm := newBitmap()
   122  		for i := 0; i < b.N; i++ {
   123  			addr := addrs[i%len(addrs)]
   124  			bm.markRange(addr, uintptr(rlen))
   125  		}
   126  	}
   127  	for rlen := 1; rlen <= 4096; rlen *= 8 {
   128  		b.Run(fmt.Sprintf("%d", rlen), func(b *testing.B) { doit(b, rlen) })
   129  	}
   130  }