From 94dbbdca7be5e4e6f73e802e8c5ad510e14e7446 Mon Sep 17 00:00:00 2001 From: Edd Robinson <me@edd.io> Date: Tue, 13 Aug 2019 11:21:26 +0100 Subject: [PATCH] perf(storage): memoize hashmap prom labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this, each hashmap operation that was instrumented involved initialising a map. Now these maps are pre-initialised. ``` ⇒ benchstat old.txt new.txt name old time/op new time/op delta Index_CreateSeriesListIfNotExist/create_series-8 5.00s ± 3% 5.13s ± 2% +2.50% (p=0.033 n=10+7) Index_CreateSeriesListIfNotExist/already_exist_series-8 557ms ± 3% 530ms ± 6% -4.85% (p=0.001 n=10+8) name old alloc/op new alloc/op delta Index_CreateSeriesListIfNotExist/create_series-8 2.57GB ± 0% 1.84GB ± 1% -28.52% (p=0.000 n=8+10) Index_CreateSeriesListIfNotExist/already_exist_series-8 678MB ± 0% 308MB ± 0% -54.55% (p=0.000 n=10+8) name old allocs/op new allocs/op delta Index_CreateSeriesListIfNotExist/create_series-8 28.9M ± 0% 24.5M ± 0% -15.22% (p=0.000 n=9+10) Index_CreateSeriesListIfNotExist/already_exist_series-8 2.23M ± 0% 0.03M ± 0% -98.51% (p=0.000 n=10+10) ``` --- pkg/rhh/rhh.go | 64 +++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/pkg/rhh/rhh.go b/pkg/rhh/rhh.go index 3586b84092..2b50414c31 100644 --- a/pkg/rhh/rhh.go +++ b/pkg/rhh/rhh.go @@ -278,23 +278,41 @@ func (m *HashMap) PrometheusCollectors() []prometheus.Collector { } type rhhTracker struct { - metrics *Metrics - labels prometheus.Labels - enabled bool + metrics *Metrics + enabled bool + baseLabels prometheus.Labels + + // Prevent allocations by initialising these static maps when creating a + // new tracker. + hitIncLabels prometheus.Labels + missIncLabels prometheus.Labels } // Labels returns a copy of the default labels used by the tracker's metrics. // The returned map is safe for modification. func (t *rhhTracker) Labels() prometheus.Labels { - labels := make(prometheus.Labels, len(t.labels)) - for k, v := range t.labels { + labels := make(prometheus.Labels, len(t.baseLabels)) + for k, v := range t.baseLabels { labels[k] = v } return labels } func newRHHTracker(metrics *Metrics, defaultLabels prometheus.Labels) *rhhTracker { - return &rhhTracker{metrics: metrics, labels: defaultLabels, enabled: true} + tracker := &rhhTracker{metrics: metrics, enabled: true} + + // Create a copy of the provided labels. + tracker.baseLabels = make(prometheus.Labels, len(defaultLabels)) + for k, v := range defaultLabels { + tracker.baseLabels[k] = v + } + + tracker.hitIncLabels = tracker.Labels() + tracker.hitIncLabels["status"] = "hit" + tracker.missIncLabels = tracker.Labels() + tracker.missIncLabels["status"] = "miss" + + return tracker } func (t *rhhTracker) SetLoadFactor(load float64) { @@ -302,8 +320,7 @@ func (t *rhhTracker) SetLoadFactor(load float64) { return } - labels := t.Labels() - t.metrics.LoadFactor.With(labels).Set(load) + t.metrics.LoadFactor.With(t.baseLabels).Set(load) } func (t *rhhTracker) SetSize(sz uint64) { @@ -311,8 +328,7 @@ func (t *rhhTracker) SetSize(sz uint64) { return } - labels := t.Labels() - t.metrics.Size.With(labels).Set(float64(sz)) + t.metrics.Size.With(t.baseLabels).Set(float64(sz)) } func (t *rhhTracker) ObserveGet(d time.Duration) { @@ -320,9 +336,8 @@ func (t *rhhTracker) ObserveGet(d time.Duration) { return } - labels := t.Labels() - t.metrics.GetDuration.With(labels).Observe(float64(d.Nanoseconds())) - t.metrics.LastGetDuration.With(labels).Set(float64(d.Nanoseconds())) + t.metrics.GetDuration.With(t.baseLabels).Observe(float64(d.Nanoseconds())) + t.metrics.LastGetDuration.With(t.baseLabels).Set(float64(d.Nanoseconds())) } func (t *rhhTracker) ObservePut(d time.Duration) { @@ -330,9 +345,8 @@ func (t *rhhTracker) ObservePut(d time.Duration) { return } - labels := t.Labels() - t.metrics.InsertDuration.With(labels).Observe(float64(d.Nanoseconds())) - t.metrics.LastInsertDuration.With(labels).Set(float64(d.Nanoseconds())) + t.metrics.InsertDuration.With(t.baseLabels).Observe(float64(d.Nanoseconds())) + t.metrics.LastInsertDuration.With(t.baseLabels).Set(float64(d.Nanoseconds())) } func (t *rhhTracker) SetGrowDuration(d time.Duration) { @@ -340,8 +354,7 @@ func (t *rhhTracker) SetGrowDuration(d time.Duration) { return } - labels := t.Labels() - t.metrics.LastGrowDuration.With(labels).Set(d.Seconds()) + t.metrics.LastGrowDuration.With(t.baseLabels).Set(d.Seconds()) } // TODO(edd): currently no safe way to calculate this concurrently. @@ -350,8 +363,7 @@ func (t *rhhTracker) SetProbeCount(length float64) { return } - labels := t.Labels() - t.metrics.MeanProbeCount.With(labels).Set(length) + t.metrics.MeanProbeCount.With(t.baseLabels).Set(length) } func (t *rhhTracker) incGet(status string) { @@ -359,8 +371,10 @@ func (t *rhhTracker) incGet(status string) { return } - labels := t.Labels() - labels["status"] = status + labels := t.hitIncLabels + if status == "miss" { + labels = t.missIncLabels + } t.metrics.Gets.With(labels).Inc() } @@ -372,8 +386,10 @@ func (t *rhhTracker) incPut(status string) { return } - labels := t.Labels() - labels["status"] = status + labels := t.hitIncLabels + if status == "miss" { + labels = t.missIncLabels + } t.metrics.Puts.With(labels).Inc() }