diff --git a/model/signature.go b/model/signature.go index ab77ae8..cc77b19 100644 --- a/model/signature.go +++ b/model/signature.go @@ -17,6 +17,7 @@ import ( "bytes" "hash" "hash/fnv" + "sync" ) // SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is @@ -28,7 +29,7 @@ var ( // cache the signature of an empty label set. emptyLabelSignature = fnv.New64a().Sum64() - hashAndBufPool = make(chan *hashAndBuf, 1024) + hashAndBufPool sync.Pool ) type hashAndBuf struct { @@ -37,19 +38,15 @@ type hashAndBuf struct { } func getHashAndBuf() *hashAndBuf { - select { - case hb := <-hashAndBufPool: - return hb - default: + hb := hashAndBufPool.Get() + if hb == nil { return &hashAndBuf{h: fnv.New64a()} } + return hb.(*hashAndBuf) } func putHashAndBuf(hb *hashAndBuf) { - select { - case hashAndBufPool <- hb: - default: - } + hashAndBufPool.Put(hb) } // LabelsToSignature returns a unique signature (i.e., fingerprint) for a given diff --git a/model/signature_test.go b/model/signature_test.go index be31998..7b3327d 100644 --- a/model/signature_test.go +++ b/model/signature_test.go @@ -15,6 +15,7 @@ package model import ( "runtime" + "sync" "testing" ) @@ -216,3 +217,40 @@ func TestEmptyLabelSignature(t *testing.T) { t.Fatal("expected LabelsToSignature with empty labels not to perform allocations") } } + +func benchmarkMetricToFingerprintConc(b *testing.B, m Metric, e Fingerprint, concLevel int) { + var start, end sync.WaitGroup + start.Add(1) + end.Add(concLevel) + + for i := 0; i < concLevel; i++ { + go func() { + start.Wait() + for j := b.N / concLevel; j >= 0; j-- { + if a := metricToFingerprint(m); a != e { + b.Fatalf("expected signature of %d for %s, got %d", e, m, a) + } + } + end.Done() + }() + } + b.ResetTimer() + start.Done() + end.Wait() +} + +func BenchmarkMetricToFingerprintTripleConc1(b *testing.B) { + benchmarkMetricToFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1) +} + +func BenchmarkMetricToFingerprintTripleConc2(b *testing.B) { + benchmarkMetricToFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2) +} + +func BenchmarkMetricToFingerprintTripleConc4(b *testing.B) { + benchmarkMetricToFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4) +} + +func BenchmarkMetricToFingerprintTripleConc8(b *testing.B) { + benchmarkMetricToFingerprintConc(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8) +}