From cbe221c9698656883b431bd0a03fe34d3d2afb13 Mon Sep 17 00:00:00 2001 From: beorn7 Date: Wed, 4 Mar 2015 12:35:06 +0100 Subject: [PATCH 1/2] Switch to sync.Pool. sync.Pool is after all faster than the home-made free list. Especially under contention. To prove that, this commit also adds a benchmark for concurrent fingerprint calculation. Benchmark results: (Run with -cpu=1,2,4. x-y -> x goroutines with GOMAXPROCS=y.) benchmark old ns/op new ns/op delta BenchmarkMetricToFingerprintTripleConc4-4 320 138 -56.88% BenchmarkMetricToFingerprintTripleConc8-4 314 141 -55.10% BenchmarkMetricToFingerprintTripleConc4-2 344 264 -23.26% BenchmarkMetricToFingerprintTripleConc2-4 331 256 -22.66% BenchmarkMetricToFingerprintTripleConc8-2 338 263 -22.19% BenchmarkMetricToFingerprintTripleConc1-4 599 505 -15.69% BenchmarkMetricToFingerprintTripleConc4 553 493 -10.85% BenchmarkMetricToFingerprintTripleConc2-2 327 292 -10.70% BenchmarkMetricToFingerprintTripleConc8 554 496 -10.47% BenchmarkMetricToFingerprintTripleConc2 555 501 -9.73% BenchmarkMetricToFingerprintTripleConc1 554 509 -8.12% BenchmarkMetricToFingerprintTripleConc1-2 551 513 -6.90% --- model/signature.go | 15 ++++++--------- model/signature_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) 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) +} From 330e2c938aada5a2fc9b4847233c3bc1ddd0e3b7 Mon Sep 17 00:00:00 2001 From: beorn7 Date: Wed, 4 Mar 2015 12:41:07 +0100 Subject: [PATCH 2/2] Use go1.4.2 in Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd4f9ab..5185359 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ MAC_OS_X_VERSION ?= 10.8 BUILD_PATH = $(PWD)/.build -export GO_VERSION = 1.4 +export GO_VERSION = 1.4.2 export GOOS = $(subst Darwin,darwin,$(subst Linux,linux,$(subst FreeBSD,freebsd,$(OS)))) ifeq ($(GOOS),darwin)