diff options
author | John Howard <howardjohn@google.com> | 2021-10-21 10:28:09 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-21 13:28:09 -0400 |
commit | bf52d9df8bb2d44cad934587ab946794456cf3c8 (patch) | |
tree | fc03ba575cdbfe00f4d9f014201eecac496a0969 | |
parent | ad0b46e7279e8f1810a49cb1e8bb29bf725f4373 (diff) | |
download | opencensus-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.go | 6 | ||||
-rw-r--r-- | stats/record.go | 4 | ||||
-rw-r--r-- | stats/view/worker.go | 13 |
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(), } |