Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit a55fb71

Browse files
authored
Optimize Record() to avoid extra allocations (#1267)
* Register metrics in benchmark Currently, the metric we record is not registered. This hits the fast-path code of not actually recording the metric, so we miss out on detecting any performance to that main code path. This registers the metrics so we actually trigger `record`. * Optimize Record() to avoid extra allocations Currently, `Record()` re-uses code with `RecordWithOptions`. This always creates allocations for createRecordOption, which is not needed in this case - we only have measurements and not generic options. With a little code duplication, we can reduce these allocations. ``` name old time/op new time/op delta Record0-6 92.2ns ± 9% 1.7ns ± 4% -98.11% (p=0.008 n=5+5) Record1-6 665ns ± 5% 634ns ± 6% -4.57% (p=0.095 n=5+5) Record8-6 1.24µs ± 5% 1.21µs ± 5% -2.18% (p=0.206 n=5+5) Record8_WithRecorder-6 796ns ± 5% 777ns ± 5% -2.45% (p=0.222 n=5+5) Record8_Parallel-6 1.21µs ± 2% 1.26µs ±24% ~ (p=0.690 n=5+5) Record8_8Tags-6 1.23µs ± 4% 1.23µs ± 2% ~ (p=0.968 n=5+5) name old alloc/op new alloc/op delta Record0-6 80.0B ± 0% 0.0B -100.00% (p=0.008 n=5+5) Record1-6 200B ± 0% 120B ± 0% -40.00% (p=0.008 n=5+5) Record8-6 424B ± 0% 344B ± 0% -18.87% (p=0.008 n=5+5) Record8_WithRecorder-6 424B ± 0% 424B ± 0% ~ (all equal) Record8_Parallel-6 424B ± 0% 344B ± 0% -18.87% (p=0.008 n=5+5) Record8_8Tags-6 424B ± 0% 344B ± 0% -18.87% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Record0-6 1.00 ± 0% 0.00 -100.00% (p=0.008 n=5+5) Record1-6 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.008 n=5+5) Record8-6 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.008 n=5+5) Record8_WithRecorder-6 4.00 ± 0% 4.00 ± 0% ~ (all equal) Record8_Parallel-6 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.008 n=5+5) Record8_8Tags-6 4.00 ± 0% 3.00 ± 0% -25.00% (p=0.008 n=5+5) ```
1 parent dcf8515 commit a55fb71

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

stats/benchmark_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,13 @@ func BenchmarkRecord8_8Tags(b *testing.B) {
109109
}
110110

111111
func makeMeasure() *stats.Int64Measure {
112-
return stats.Int64("m", "test measure", "")
112+
m := stats.Int64("m", "test measure", "")
113+
v := &view.View{
114+
Measure: m,
115+
Aggregation: view.Sum(),
116+
}
117+
if err := view.Register(v); err != nil {
118+
panic(err.Error())
119+
}
120+
return m
113121
}

stats/record.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,24 @@ func createRecordOption(ros ...Options) *recordOptions {
8989
// Record records one or multiple measurements with the same context at once.
9090
// If there are any tags in the context, measurements will be tagged with them.
9191
func Record(ctx context.Context, ms ...Measurement) {
92-
RecordWithOptions(ctx, WithMeasurements(ms...))
92+
// Record behaves the same as RecordWithOptions, but because we do not have to handle generic functionality
93+
// (RecordOptions) we can reduce some allocations to speed up this hot path
94+
if len(ms) == 0 {
95+
return
96+
}
97+
recorder := internal.DefaultRecorder
98+
record := false
99+
for _, m := range ms {
100+
if m.desc.subscribed() {
101+
record = true
102+
break
103+
}
104+
}
105+
if !record {
106+
return
107+
}
108+
recorder(tag.FromContext(ctx), ms, nil)
109+
return
93110
}
94111

95112
// RecordWithTags records one or multiple measurements at once.

0 commit comments

Comments
 (0)