perf(storage): memoize hashmap prom labels

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)
```
pull/14638/head
Edd Robinson 2019-08-13 11:21:26 +01:00
parent 9f3cbdc80e
commit 94dbbdca7b
1 changed files with 40 additions and 24 deletions

View File

@ -279,22 +279,40 @@ func (m *HashMap) PrometheusCollectors() []prometheus.Collector {
type rhhTracker struct {
metrics *Metrics
labels prometheus.Labels
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()
}