Skip to content

Commit 8ada166

Browse files
committed
index for bit optimization
Signed-off-by: jsign <[email protected]>
1 parent b2c774a commit 8ada166

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

hamt_bench_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package hamt
33
import (
44
"context"
55
"encoding/hex"
6+
"fmt"
67
"math/rand"
78
"runtime"
89
"testing"
@@ -47,6 +48,40 @@ func BenchmarkSerializeNode(b *testing.B) {
4748
}
4849
}
4950

51+
type benchSetCase struct {
52+
count int
53+
bitwidth int
54+
}
55+
56+
func BenchmarkSet(b *testing.B) {
57+
kCounts := []int{1, 10, 100}
58+
bitwidths := []int{5, 8}
59+
60+
var table []benchSetCase
61+
for _, c := range kCounts {
62+
63+
for _, bw := range bitwidths {
64+
table = append(table, benchSetCase{count: c * 1000, bitwidth: bw})
65+
}
66+
67+
}
68+
r := rander{rand.New(rand.NewSource(int64(42)))}
69+
for _, t := range table {
70+
b.Run(fmt.Sprintf("%d/%d", t.count, t.bitwidth), func(b *testing.B) {
71+
ctx := context.Background()
72+
n := NewNode(NewCborStore(), UseTreeBitWidth(t.bitwidth))
73+
b.ResetTimer()
74+
for i := 0; i < b.N; i++ {
75+
for j := 0; j < t.count; j++ {
76+
if err := n.Set(ctx, r.randString(), r.randValue()); err != nil {
77+
b.Fatal(err)
78+
}
79+
}
80+
}
81+
})
82+
}
83+
}
84+
5085
func BenchmarkFind(b *testing.B) {
5186
b.Run("find-10k", doBenchmarkEntriesCount(10000, 8))
5287
b.Run("find-100k", doBenchmarkEntriesCount(100000, 8))

uhamt.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
// indexForBitPos returns the index within the collapsed array corresponding to
99
// the given bit in the bitset. The collapsed array contains only one entry
1010
// per bit set in the bitfield, and this function is used to map the indices.
11-
func (n *Node) indexForBitPos(bp int) int {
11+
func (n *Node) indexForBitPosOld(bp int) int {
1212
// TODO: an optimization could reuse the same 'mask' here and change the size
1313
// as needed. This isnt yet done as the bitset package doesnt make it easy
1414
// to do.
@@ -27,3 +27,17 @@ func popCount(i *big.Int) int {
2727
}
2828
return n
2929
}
30+
31+
func (n *Node) indexForBitPos(bp int) int {
32+
var x uint64
33+
var count, i int
34+
w := n.Bitfield.Bits()
35+
for x = uint64(bp); x > 64 && i < len(w); x -= 64 {
36+
count += bits.OnesCount64(uint64(w[i]))
37+
i++
38+
}
39+
if i == len(w) {
40+
return count
41+
}
42+
return count + bits.OnesCount64(uint64(w[i])&((1<<x)-1))
43+
}

0 commit comments

Comments
 (0)