Skip to content

Commit

Permalink
benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
sgreben committed Sep 19, 2024
1 parent 7939f2b commit 4411f01
Show file tree
Hide file tree
Showing 4 changed files with 370 additions and 3 deletions.
92 changes: 90 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,99 @@ func main() {

### Top-K Sketch

(TBD)
```
goos: darwin
goarch: arm64
pkg: github.com/keilerkonzept/topk/sliding
cpu: Apple M1 Pro
```

| Operation | K | Depth | Width | time/op | bytes/op | allocs/op |
|-----------|----:|------:|------:|------------:|---------:|------------:|
| `Add` | 10 | 3 | 1024 | 358.6 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 3 | 8192 | 375.0 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 4 | 1024 | 449.9 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 4 | 8192 | 436.0 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 1024 | 371.5 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 8192 | 387.9 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 4 | 1024 | 452.3 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 4 | 8192 | 471.4 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 1024 | 257.2 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 8192 | 232.3 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 4 | 1024 | 249.1 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 4 | 8192 | 251.2 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 1024 | 264.2 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 8192 | 227.4 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 4 | 1024 | 267.1 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 4 | 8192 | 261.3 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 1024 | 216.0 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 8192 | 215.4 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 4 | 1024 | 220.0 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 4 | 8192 | 269.3 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 1024 | 235.1 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 8192 | 277.1 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 4 | 1024 | 278.7 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 4 | 8192 | 302.2 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 1024 | 129.6 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 8192 | 98.21 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 4 | 1024 | 129.9 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 4 | 8192 | 114.3 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 1024 | 141.2 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 8192 | 140.8 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 4 | 1024 | 131.1 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 4 | 8192 | 109.8 ns/op | 0 B/op | 0 allocs/op |

### Sliding-Window Top-K Sketch

(TBD)
```
goos: darwin
goarch: arm64
pkg: github.com/keilerkonzept/topk/sliding
cpu: Apple M1 Pro
```

| Operation | K | Depth | Width | Window size (ticks) | History buckets | time/op | bytes/op | allocs/op |
| --------- | ---: | ----: | ----: | ------------------: | --------------: | ----------: | -------: | ----------: |
| `Add` | 10 | 3 | 1024 | 100 | 50 | 696.9 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 3 | 1024 | 100 | 100 | 1051 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 3 | 8192 | 100 | 50 | 784.9 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 10 | 3 | 8192 | 100 | 100 | 1146 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 1024 | 100 | 50 | 712.9 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 1024 | 100 | 100 | 1054 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 8192 | 100 | 50 | 763.3 ns/op | 0 B/op | 0 allocs/op |
| `Add` | 100 | 3 | 8192 | 100 | 100 | 1139 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 1024 | 100 | 50 | 434.9 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 1024 | 100 | 100 | 560.7 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 8192 | 100 | 50 | 501.1 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 10 | 3 | 8192 | 100 | 100 | 728.7 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 1024 | 100 | 50 | 425.6 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 1024 | 100 | 100 | 580.0 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 8192 | 100 | 50 | 497.8 ns/op | 0 B/op | 0 allocs/op |
| `Incr` | 100 | 3 | 8192 | 100 | 100 | 746.2 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 1024 | 100 | 50 | 228.5 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 1024 | 100 | 100 | 209.3 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 8192 | 100 | 50 | 234.5 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 10 | 3 | 8192 | 100 | 100 | 230.7 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 1024 | 100 | 50 | 237.5 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 1024 | 100 | 100 | 242.8 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 8192 | 100 | 50 | 246.5 ns/op | 0 B/op | 0 allocs/op |
| `Count` | 100 | 3 | 8192 | 100 | 100 | 243.4 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 1024 | 100 | 50 | 101.7 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 1024 | 100 | 100 | 104.8 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 8192 | 100 | 50 | 114.0 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 10 | 3 | 8192 | 100 | 100 | 114.5 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 1024 | 100 | 50 | 135.9 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 1024 | 100 | 100 | 118.5 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 8192 | 100 | 50 | 130.1 ns/op | 0 B/op | 0 allocs/op |
| `Query` | 100 | 3 | 8192 | 100 | 100 | 131.5 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 10 | 3 | 1024 | 100 | 50 | 4191 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 10 | 3 | 1024 | 100 | 100 | 7010 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 10 | 3 | 8192 | 100 | 50 | 28699 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 10 | 3 | 8192 | 100 | 100 | 90979 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 100 | 3 | 1024 | 100 | 50 | 6539 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 100 | 3 | 1024 | 100 | 100 | 9343 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 100 | 3 | 8192 | 100 | 50 | 31349 ns/op | 0 B/op | 0 allocs/op |
| `Tick` | 100 | 3 | 8192 | 100 | 100 | 87488 ns/op | 0 B/op | 0 allocs/op |

### Decay LUT impact

Expand Down
114 changes: 114 additions & 0 deletions sketch_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package topk_test

import (
"fmt"
"math/rand/v2"
"testing"

"github.com/keilerkonzept/topk"
)

var (
ks = []int{10, 100}
depths = []int{3, 4}
widths = []int{1024, 8192}
items = generateItems(1_000_000)
)

func generateItems(n int) []string {
items := make([]string, n)
for i := 0; i < n; i++ {
items[i] = fmt.Sprintf("item%d", i)
}
return items
}

// BenchmarkSketchAdd benchmarks the Add method of Sketch.
func BenchmarkSketchAdd(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d", k, depth, width), func(b *testing.B) {
sketch := topk.New(k,
topk.WithDepth(depth),
topk.WithWidth(width),
)

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Add(items[rand.IntN(len(items))], uint32(rand.IntN(10)))
}
})
}
}
}
}

// BenchmarkSketchIncr benchmarks the Incr method of Sketch.
func BenchmarkSketchIncr(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d", k, depth, width), func(b *testing.B) {
sketch := topk.New(k,
topk.WithDepth(depth),
topk.WithWidth(width),
)

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Incr(items[rand.IntN(len(items))])
}
})
}
}
}
}

// BenchmarkSketchCount benchmarks the Count method of Sketch.
func BenchmarkSketchCount(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d", k, depth, width), func(b *testing.B) {
sketch := topk.New(k,
topk.WithDepth(depth),
topk.WithWidth(width),
)
for _, item := range items {
sketch.Add(item, uint32(rand.IntN(10)))
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Count(items[rand.IntN(len(items))])
}
})
}
}
}
}

// BenchmarkSketchQuery benchmarks the Query method of Sketch.
func BenchmarkSketchQuery(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d", k, depth, width), func(b *testing.B) {
sketch := topk.New(k,
topk.WithDepth(depth),
topk.WithWidth(width),
)
for _, item := range items {
sketch.Add(item, uint32(rand.IntN(10)))
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Query(items[rand.IntN(len(items))])
}
})
}
}
}
}
2 changes: 1 addition & 1 deletion sliding/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (me *Bucket) findNonzeroMinimumCount() int {
first := true
var countsMin uint32
i := me.First
for range len(me.Counts) {
for range me.Counts {
if i == uint32(len(me.Counts)) {
i = 0
}
Expand Down
165 changes: 165 additions & 0 deletions sliding/sketch_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package sliding_test

import (
"fmt"
"math/rand/v2"
"testing"

"github.com/keilerkonzept/topk/sliding"
)

var (
ks = []int{10, 100}
depths = []int{3}
widths = []int{1024, 8192}
windowSizes = []int{100}
items = generateItems(1_000_000)
)

func generateItems(n int) []string {
items := make([]string, n)
for i := 0; i < n; i++ {
items[i] = fmt.Sprintf("item%d", i)
}
return items
}

// BenchmarkSketchAdd benchmarks the Add method of Sketch.
func BenchmarkSketchAdd(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
for _, windowSize := range windowSizes {
for _, historyLen := range []int{windowSize / 2, windowSize} {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d_WindowSize=%d_HistoryLen=%d", k, depth, width, windowSize, historyLen), func(b *testing.B) {
sketch := sliding.New(k, windowSize,
sliding.WithDepth(depth),
sliding.WithWidth(width),
sliding.WithBucketHistoryLength(historyLen),
)

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Add(items[rand.IntN(len(items))], uint32(rand.IntN(10)))
}
})
}
}
}
}
}
}

// BenchmarkSketchIncr benchmarks the Incr method of Sketch.
func BenchmarkSketchIncr(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
for _, windowSize := range windowSizes {
for _, historyLen := range []int{windowSize / 2, windowSize} {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d_WindowSize=%d_HistoryLen=%d", k, depth, width, windowSize, historyLen), func(b *testing.B) {
sketch := sliding.New(k, windowSize,
sliding.WithDepth(depth),
sliding.WithWidth(width),
sliding.WithBucketHistoryLength(historyLen),
)

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Incr(items[rand.IntN(len(items))])
}
})
}
}
}
}
}
}

// BenchmarkSketchCount benchmarks the Count method of Sketch.
func BenchmarkSketchCount(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
for _, windowSize := range windowSizes {
for _, historyLen := range []int{windowSize / 2, windowSize} {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d_WindowSize=%d_HistoryLen=%d", k, depth, width, windowSize, historyLen), func(b *testing.B) {
sketch := sliding.New(k, windowSize,
sliding.WithDepth(depth),
sliding.WithWidth(width),
sliding.WithBucketHistoryLength(historyLen),
)
for _, item := range items {
sketch.Add(item, uint32(rand.IntN(10)))
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Count(items[rand.IntN(len(items))])
}
})
}
}
}
}
}
}

// BenchmarkSketchQuery benchmarks the Query method of Sketch.
func BenchmarkSketchQuery(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
for _, windowSize := range windowSizes {
for _, historyLen := range []int{windowSize / 2, windowSize} {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d_WindowSize=%d_HistoryLen=%d", k, depth, width, windowSize, historyLen), func(b *testing.B) {
sketch := sliding.New(k, windowSize,
sliding.WithDepth(depth),
sliding.WithWidth(width),
sliding.WithBucketHistoryLength(historyLen),
)
for _, item := range items {
sketch.Add(item, uint32(rand.IntN(10)))
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Query(items[rand.IntN(len(items))])
}
})
}
}
}
}
}
}

// BenchmarkSketchTick benchmarks the Tick method of Sketch.
func BenchmarkSketchTick(b *testing.B) {
for _, k := range ks {
for _, depth := range depths {
for _, width := range widths {
for _, windowSize := range windowSizes {
for _, historyLen := range []int{windowSize / 2, windowSize} {
b.Run(fmt.Sprintf("K=%d_Depth=%d_Width=%d_WindowSize=%d_HistoryLen=%d", k, depth, width, windowSize, historyLen), func(b *testing.B) {
sketch := sliding.New(k, windowSize,
sliding.WithDepth(depth),
sliding.WithWidth(width),
sliding.WithBucketHistoryLength(historyLen),
)

for _, item := range items {
sketch.Add(item, uint32(rand.IntN(10)))
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
sketch.Tick()
}
})
}
}
}
}
}
}

0 comments on commit 4411f01

Please sign in to comment.