Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pool metric options created in the otelhttp instrumentation #5968

Closed
2 tasks
MadVikingGod opened this issue Aug 1, 2024 · 5 comments · Fixed by #6394
Closed
2 tasks

Pool metric options created in the otelhttp instrumentation #5968

MadVikingGod opened this issue Aug 1, 2024 · 5 comments · Fixed by #6394
Assignees
Labels
contribfest help wanted Extra attention is needed
Milestone

Comments

@MadVikingGod
Copy link
Contributor

MadVikingGod commented Aug 1, 2024

Pooling the options created by otelhttp instrumentation should reduce allocations and improve performance.

Tasks

  • Use a pool when creating metric options.
  • Create benchmark showing this does reduce allocations.

Originally posted by @MrAlias in #5818 (comment)

@vordimous
Copy link
Contributor

This looks to be a straightforward pool for the objects created in RecordMetrics(). What is the best way to benchmark the number of allocations? I would like to take on this issue.

@dmathieu
Copy link
Member

dmathieu commented Dec 2, 2024

A benchmark with the ReportAllocs option will allow you to compare the number of allocations between two different implementations.

See this as an example:

@vordimous
Copy link
Contributor

I have implemnted two benchmark functions in env_test.go that run the same code as the TestHTTPServerDoesNotPanic(). I added a benchmark for the unpooled code and pooled code with both reporting 0 allocs/op. I may have done something wrong or identified that pooling isn't needed?

BenchmarkRecordMetricsPooled-10    	1000000000	         0.0000000 ns/op	       0 B/op	       0 allocs/op
BenchmarkRecordMetrics-10          	1000000000	         0.0000001 ns/op	       0 B/op	       0 allocs/op

Full test results:

Running tool: /opt/homebrew/bin/go test -timeout 30s -run ^(TestHTTPServerDoesNotPanicPooled|TestHTTPServerDoesNotPanic|TestHTTPClientDoesNotPanic)$ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv -v --bench . --benchmem

=== RUN   TestHTTPServerDoesNotPanicPooled
=== RUN   TestHTTPServerDoesNotPanicPooled/empty
=== RUN   TestHTTPServerDoesNotPanicPooled/nil_meter
=== RUN   TestHTTPServerDoesNotPanicPooled/with_Meter
--- PASS: TestHTTPServerDoesNotPanicPooled (0.00s)
    --- PASS: TestHTTPServerDoesNotPanicPooled/empty (0.00s)
    --- PASS: TestHTTPServerDoesNotPanicPooled/nil_meter (0.00s)
    --- PASS: TestHTTPServerDoesNotPanicPooled/with_Meter (0.00s)
=== RUN   TestHTTPServerDoesNotPanic
=== RUN   TestHTTPServerDoesNotPanic/empty
=== RUN   TestHTTPServerDoesNotPanic/nil_meter
=== RUN   TestHTTPServerDoesNotPanic/with_Meter
--- PASS: TestHTTPServerDoesNotPanic (0.00s)
    --- PASS: TestHTTPServerDoesNotPanic/empty (0.00s)
    --- PASS: TestHTTPServerDoesNotPanic/nil_meter (0.00s)
    --- PASS: TestHTTPServerDoesNotPanic/with_Meter (0.00s)
=== RUN   TestHTTPClientDoesNotPanic
=== RUN   TestHTTPClientDoesNotPanic/empty
=== RUN   TestHTTPClientDoesNotPanic/nil_meter
=== RUN   TestHTTPClientDoesNotPanic/with_Meter
--- PASS: TestHTTPClientDoesNotPanic (0.00s)
    --- PASS: TestHTTPClientDoesNotPanic/empty (0.00s)
    --- PASS: TestHTTPClientDoesNotPanic/nil_meter (0.00s)
    --- PASS: TestHTTPClientDoesNotPanic/with_Meter (0.00s)
goos: darwin
goarch: arm64
pkg: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
cpu: Apple M1 Max
BenchmarkHTTPServerRequest
BenchmarkHTTPServerRequest-10      	 4002741	       290.8 ns/op	     712 B/op	       2 allocs/op
BenchmarkRecordMetricsPooled
BenchmarkRecordMetricsPooled-10    	1000000000	         0.0000000 ns/op	       0 B/op	       0 allocs/op
BenchmarkRecordMetrics
BenchmarkRecordMetrics-10          	1000000000	         0.0000001 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv	1.752s

@dmathieu
Copy link
Member

dmathieu commented Dec 2, 2024

Could you open a PR with the code change and benchmark? That would provide the appropriate data to review your analysis.

@vordimous
Copy link
Contributor

@dmathieu I have created the PR with new method and benchmarks: #6394

@MrAlias MrAlias added this to the v1.33.0 milestone Dec 12, 2024
@MrAlias MrAlias moved this from Todo to In Progress in Go: HTTP Semconv Migration Dec 12, 2024
MrAlias added a commit that referenced this issue Dec 12, 2024
This PR improves the `RecordMetrics()` allocations using a pool for the
`metric.AddOption` slice.

`benchstat main.txt pool.txt`:
```
goos: darwin
goarch: arm64
pkg: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv
cpu: Apple M1 Max
                            │  main.txt   │              pool.txt              │
                            │   sec/op    │   sec/op     vs base               │
RecordMetrics/empty-10        4.513n ± 3%   4.620n ± 0%  +2.38% (p=0.037 n=10)
RecordMetrics/nil_meter-10    341.8n ± 1%   330.7n ± 4%  -3.26% (p=0.022 n=10)
RecordMetrics/with_Meter-10   341.1n ± 1%   330.0n ± 1%  -3.27% (p=0.000 n=10)
geomean                       80.74n        79.59n       -1.42%

                            │   main.txt   │              pool.txt               │
                            │     B/op     │    B/op     vs base                 │
RecordMetrics/empty-10        0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
RecordMetrics/nil_meter-10    696.0 ± 0%     680.0 ± 0%  -2.30% (p=0.000 n=10)
RecordMetrics/with_Meter-10   696.0 ± 0%     680.0 ± 0%  -2.30% (p=0.000 n=10)
geomean                                  ²               -1.54%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                            │   main.txt   │               pool.txt               │
                            │  allocs/op   │ allocs/op   vs base                  │
RecordMetrics/empty-10        0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
RecordMetrics/nil_meter-10    6.000 ± 0%     5.000 ± 0%  -16.67% (p=0.000 n=10)
RecordMetrics/with_Meter-10   6.000 ± 0%     5.000 ± 0%  -16.67% (p=0.000 n=10)
geomean                                  ²               -11.45%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean
```

Fixes
#5968

---------

Co-authored-by: Damien Mathieu <[email protected]>
Co-authored-by: Tyler Yahn <[email protected]>
@github-project-automation github-project-automation bot moved this from In Progress to Done in Go: HTTP Semconv Migration Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribfest help wanted Extra attention is needed
Projects
Development

Successfully merging a pull request may close this issue.

4 participants