Browse Source

Merge pull request #242 from nightlyone/each_no_copy

speed up registry Each method
Mikhail P 6 years ago
parent
commit
9c2d0518ed
2 changed files with 31 additions and 5 deletions
  1. 15 5
      registry.go
  2. 16 0
      registry_test.go

+ 15 - 5
registry.go

@@ -64,8 +64,10 @@ func NewRegistry() Registry {
 
 
 // Call the given function for each registered metric.
 // Call the given function for each registered metric.
 func (r *StandardRegistry) Each(f func(string, interface{})) {
 func (r *StandardRegistry) Each(f func(string, interface{})) {
-	for name, i := range r.registered() {
-		f(name, i)
+	metrics := r.registered()
+	for i := range metrics {
+		kv := &metrics[i]
+		f(kv.name, kv.value)
 	}
 	}
 }
 }
 
 
@@ -211,12 +213,20 @@ func (r *StandardRegistry) register(name string, i interface{}) error {
 	return nil
 	return nil
 }
 }
 
 
-func (r *StandardRegistry) registered() map[string]interface{} {
+type metricKV struct {
+	name  string
+	value interface{}
+}
+
+func (r *StandardRegistry) registered() []metricKV {
+	metrics := make([]metricKV, 0, len(r.metrics))
 	r.mutex.RLock()
 	r.mutex.RLock()
 	defer r.mutex.RUnlock()
 	defer r.mutex.RUnlock()
-	metrics := make(map[string]interface{}, len(r.metrics))
 	for name, i := range r.metrics {
 	for name, i := range r.metrics {
-		metrics[name] = i
+		metrics = append(metrics, metricKV{
+			name:  name,
+			value: i,
+		})
 	}
 	}
 	return metrics
 	return metrics
 }
 }

+ 16 - 0
registry_test.go

@@ -1,6 +1,7 @@
 package metrics
 package metrics
 
 
 import (
 import (
+	"fmt"
 	"sync"
 	"sync"
 	"testing"
 	"testing"
 )
 )
@@ -14,6 +15,21 @@ func BenchmarkRegistry(b *testing.B) {
 	}
 	}
 }
 }
 
 
+func BenchmarkHugeRegistry(b *testing.B) {
+	r := NewRegistry()
+	for i := 0; i < 10000; i++ {
+		r.Register(fmt.Sprintf("foo%07d", i), NewCounter())
+	}
+	v := make([]string, 10000)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		v := v[:0]
+		r.Each(func(k string, _ interface{}) {
+			v = append(v, k)
+		})
+	}
+}
+
 func BenchmarkRegistryParallel(b *testing.B) {
 func BenchmarkRegistryParallel(b *testing.B) {
 	r := NewRegistry()
 	r := NewRegistry()
 	b.ResetTimer()
 	b.ResetTimer()