summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Howard <howardjohn@google.com>2021-10-21 10:28:09 -0700
committerGitHub <noreply@github.com>2021-10-21 13:28:09 -0400
commitbf52d9df8bb2d44cad934587ab946794456cf3c8 (patch)
treefc03ba575cdbfe00f4d9f014201eecac496a0969
parentad0b46e7279e8f1810a49cb1e8bb29bf725f4373 (diff)
downloadopencensus-go-bf52d9df8bb2d44cad934587ab946794456cf3c8.tar.gz
Remove `convTslice` calls in Record() (#1268)
* Remove `convTslice` calls in `Record()` This is built upon https://github.com/census-instrumentation/opencensus-go/pull/1267; that one should likely merge first. I split this out as it has a small public API change (to work around circular imports) to avoid issues on the first PR. Benchmark relative to #1267: ``` me old time/op new time/op delta Record0-6 1.74ns ± 4% 1.79ns ± 2% +2.85% (p=0.238 n=5+5) Record1-6 634ns ± 6% 542ns ± 9% -14.55% (p=0.008 n=5+5) Record8-6 1.21µs ± 5% 1.23µs ± 2% +1.97% (p=0.254 n=5+5) Record8_WithRecorder-6 777ns ± 5% 792ns ± 5% +1.97% (p=0.421 n=5+5) Record8_Parallel-6 1.26µs ±24% 1.22µs ± 2% ~ (p=0.690 n=5+5) Record8_8Tags-6 1.23µs ± 2% 1.25µs ± 3% ~ (p=0.651 n=5+5) name old alloc/op new alloc/op delta Record0-6 0.00B 0.00B ~ (all equal) Record1-6 120B ± 0% 96B ± 0% -20.00% (p=0.008 n=5+5) Record8-6 344B ± 0% 320B ± 0% -6.98% (p=0.008 n=5+5) Record8_WithRecorder-6 424B ± 0% 424B ± 0% ~ (all equal) Record8_Parallel-6 344B ± 0% 320B ± 0% -6.98% (p=0.008 n=5+5) Record8_8Tags-6 344B ± 0% 320B ± 0% -6.98% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Record0-6 0.00 0.00 ~ (all equal) Record1-6 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.008 n=5+5) Record8-6 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.008 n=5+5) Record8_WithRecorder-6 4.00 ± 0% 4.00 ± 0% ~ (all equal) Record8_Parallel-6 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.008 n=5+5) Record8_8Tags-6 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.008 n=5+5) ``` * Refactor to avoid leaking into public API
-rw-r--r--stats/internal/record.go6
-rw-r--r--stats/record.go4
-rw-r--r--stats/view/worker.go13
3 files changed, 21 insertions, 2 deletions
diff --git a/stats/internal/record.go b/stats/internal/record.go
index 36935e6..436dc79 100644
--- a/stats/internal/record.go
+++ b/stats/internal/record.go
@@ -21,5 +21,11 @@ import (
// DefaultRecorder will be called for each Record call.
var DefaultRecorder func(tags *tag.Map, measurement interface{}, attachments map[string]interface{})
+// MeasurementRecorder will be called for each Record call. This is the same as DefaultRecorder but
+// avoids interface{} conversion.
+// This will be a func(tags *tag.Map, measurement []Measurement, attachments map[string]interface{}) type,
+// but is interface{} here to avoid import loops
+var MeasurementRecorder interface{}
+
// SubscriptionReporter reports when a view subscribed with a measure.
var SubscriptionReporter func(measure string)
diff --git a/stats/record.go b/stats/record.go
index f8a52bc..8b5b998 100644
--- a/stats/record.go
+++ b/stats/record.go
@@ -86,6 +86,8 @@ func createRecordOption(ros ...Options) *recordOptions {
return o
}
+type measurementRecorder = func(tags *tag.Map, measurement []Measurement, attachments map[string]interface{})
+
// Record records one or multiple measurements with the same context at once.
// If there are any tags in the context, measurements will be tagged with them.
func Record(ctx context.Context, ms ...Measurement) {
@@ -94,7 +96,7 @@ func Record(ctx context.Context, ms ...Measurement) {
if len(ms) == 0 {
return
}
- recorder := internal.DefaultRecorder
+ recorder := internal.MeasurementRecorder.(measurementRecorder)
record := false
for _, m := range ms {
if m.desc.subscribed() {
diff --git a/stats/view/worker.go b/stats/view/worker.go
index 6e8d18b..135c85a 100644
--- a/stats/view/worker.go
+++ b/stats/view/worker.go
@@ -33,6 +33,7 @@ func init() {
defaultWorker = NewMeter().(*worker)
go defaultWorker.start()
internal.DefaultRecorder = record
+ internal.MeasurementRecorder = recordMeasurement
}
type measureRef struct {
@@ -199,11 +200,21 @@ func record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
defaultWorker.Record(tags, ms, attachments)
}
+func recordMeasurement(tags *tag.Map, ms []stats.Measurement, attachments map[string]interface{}) {
+ defaultWorker.recordMeasurement(tags, ms, attachments)
+}
+
// Record records a set of measurements ms associated with the given tags and attachments.
func (w *worker) Record(tags *tag.Map, ms interface{}, attachments map[string]interface{}) {
+ w.recordMeasurement(tags, ms.([]stats.Measurement), attachments)
+}
+
+// recordMeasurement records a set of measurements ms associated with the given tags and attachments.
+// This is the same as Record but without an interface{} type to avoid allocations
+func (w *worker) recordMeasurement(tags *tag.Map, ms []stats.Measurement, attachments map[string]interface{}) {
req := &recordReq{
tm: tags,
- ms: ms.([]stats.Measurement),
+ ms: ms,
attachments: attachments,
t: time.Now(),
}