Use binary search to pick bucket.

With the usual number of buckets, this doesn't really make a
difference, but it should scale... See the added TODO for the precise
numbers.
This commit is contained in:
beorn7 2015-02-19 19:50:14 +01:00
parent 38dbb2e268
commit 79efd06178
1 changed files with 13 additions and 5 deletions

View File

@ -17,6 +17,7 @@ import (
"fmt" "fmt"
"hash/fnv" "hash/fnv"
"math" "math"
"sort"
"sync/atomic" "sync/atomic"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
@ -231,11 +232,18 @@ func (h *histogram) Desc() *Desc {
} }
func (h *histogram) Observe(v float64) { func (h *histogram) Observe(v float64) {
for i, upperBound := range h.upperBounds { // TODO(beorn7): For small numbers of buckets (<30), a linear search is
if v <= upperBound { // slightly faster than the binary search. If we really care, we could
// switch from one search strategy to the other depending on the number
// of buckets.
//
// Microbenchmarks (BenchmarkHistogramNoLabels):
// 11 buckets: 38.3 ns/op linear - binary 48.7 ns/op
// 100 buckets: 78.1 ns/op linear - binary 54.9 ns/op
// 300 buckets: 154 ns/op linear - binary 61.6 ns/op
i := sort.SearchFloat64s(h.upperBounds, v)
if i < len(h.counts) {
atomic.AddUint64(&h.counts[i], 1) atomic.AddUint64(&h.counts[i], 1)
break
}
} }
atomic.AddUint64(&h.count, 1) atomic.AddUint64(&h.count, 1)
for { for {