github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/hll/hll_test.go (about)

     1  package hll
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  
     7  	"github.com/fluhus/gostuff/bnry"
     8  	"github.com/spaolacci/murmur3"
     9  )
    10  
    11  func TestCount_short(t *testing.T) {
    12  	upto := 10000000
    13  	if testing.Short() {
    14  		upto = 1000
    15  	}
    16  
    17  	hll := newIntHLL()
    18  	next := 1
    19  	ratioSum := 0.0
    20  	ratioCount := 0.0
    21  	for i := 1; i <= upto; i++ {
    22  		hll.Add(i)
    23  		if i != next { // Check only a sample.
    24  			continue
    25  		}
    26  		next = (next + 1) * 21 / 20
    27  		ratio := float64(i) / float64(hll.ApproxCount())
    28  		ratioSum += math.Abs(math.Log(ratio))
    29  		ratioCount++
    30  	}
    31  	avg := math.Exp(ratioSum / ratioCount)
    32  	want := 1.003
    33  	if avg > want {
    34  		t.Errorf("average error=%f, want at most %f",
    35  			avg, want)
    36  	}
    37  }
    38  
    39  func TestCount_zero(t *testing.T) {
    40  	hll := newIntHLL()
    41  	if count := hll.ApproxCount(); count != 0 {
    42  		t.Fatalf("ApproxCount()=%v, want 0", count)
    43  	}
    44  }
    45  
    46  func TestAddHLL(t *testing.T) {
    47  	hll1 := newIntHLL()
    48  	for i := 1; i <= 5; i++ {
    49  		hll1.Add(i)
    50  	}
    51  	if count := hll1.ApproxCount(); count != 5 {
    52  		t.Fatalf("ApproxCount()=%v, want 5", count)
    53  	}
    54  
    55  	hll2 := newIntHLL()
    56  	for i := 4; i <= 9; i++ {
    57  		hll2.Add(i)
    58  	}
    59  	if count := hll2.ApproxCount(); count != 6 {
    60  		t.Fatalf("ApproxCount()=%v, want 6", count)
    61  	}
    62  
    63  	hll1.AddHLL(hll2)
    64  	if count := hll1.ApproxCount(); count != 9 {
    65  		t.Fatalf("ApproxCount()=%v, want 9", count)
    66  	}
    67  }
    68  
    69  func BenchmarkAdd(b *testing.B) {
    70  	hll := New2(16, func(i int) uint64 { return uint64(i) })
    71  	for i := 0; i < b.N; i++ {
    72  		hll.Add(i)
    73  	}
    74  }
    75  
    76  func BenchmarkAdd_intHLL(b *testing.B) {
    77  	hll := newIntHLL()
    78  	for i := 0; i < b.N; i++ {
    79  		hll.Add(i)
    80  	}
    81  }
    82  
    83  func BenchmarkCount(b *testing.B) {
    84  	const nelements = 1000000
    85  	hll := newIntHLL()
    86  	for i := 0; i < nelements; i++ {
    87  		hll.Add(i)
    88  	}
    89  	b.Run("", func(b *testing.B) {
    90  		for i := 0; i < b.N; i++ {
    91  			hll.ApproxCount()
    92  		}
    93  	})
    94  }
    95  
    96  func newIntHLL() *HLL2[int] {
    97  	h := murmur3.New64()
    98  	w := bnry.NewWriter(h)
    99  	return New2(16, func(i int) uint64 {
   100  		h.Reset()
   101  		w.Write(i)
   102  		return h.Sum64()
   103  	})
   104  }