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

otelzap: Use pool for encoder #5719

Closed
wants to merge 15 commits into from

Conversation

khushijain21
Copy link
Contributor

@khushijain21 khushijain21 commented Jun 4, 2024

Part of #5191

Pre-work #5279

Results:

goos: linux
goarch: amd64
pkg: go.opentelemetry.io/contrib/bridges/otelzap
cpu: 12th Gen Intel(R) Core(TM) i5-1245U
                           │ old_bench.txt │            new_bench.txt             │
                           │    sec/op     │    sec/op     vs base                │
CoreWrite/10_fields-12       1170.5n ± 28%   511.8n ± 44%  -56.28% (p=0.000 n=10)
CoreWrite/20_fields-12        2.665µ ± 24%   1.441µ ± 20%  -45.93% (p=0.000 n=10)
CoreWrite/Namespace-12        2.057µ ± 29%   1.211µ ±  5%  -41.13% (p=0.000 n=10)
CoreWrite/With10_fields-12    249.3n ± 22%   186.4n ± 21%  -25.23% (p=0.015 n=10)
CoreWrite/With20_fields-12    716.5n ± 30%   513.4n ± 40%        ~ (p=0.072 n=10)
CoreWrite/WithNamespace-12    24.39n ± 22%   14.16n ± 20%  -41.93% (p=0.000 n=10)
geomean                       550.9n         326.4n        -40.74%

                           │ old_bench.txt  │             new_bench.txt              │
                           │      B/op      │     B/op      vs base                  │
CoreWrite/10_fields-12         978.0 ± 0%       307.0 ± 0%  -68.61% (p=0.000 n=10)
CoreWrite/20_fields-12        2180.0 ± 0%       818.0 ± 0%  -62.48% (p=0.000 n=10)
CoreWrite/Namespace-12       1.719Ki ± 0%     1.002Ki ± 0%  -41.70% (p=0.000 n=10)
CoreWrite/With10_fields-12     208.0 ± 0%       208.0 ± 0%        ~ (p=1.000 n=10) ¹
CoreWrite/With20_fields-12     640.0 ± 0%       640.0 ± 0%        ~ (p=1.000 n=10) ¹
CoreWrite/WithNamespace-12     0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
geomean                                   ²                 -36.01%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                           │ old_bench.txt │            new_bench.txt             │
                           │   allocs/op   │ allocs/op   vs base                  │
CoreWrite/10_fields-12        13.00 ± 0%     10.00 ± 0%  -23.08% (p=0.000 n=10)
CoreWrite/20_fields-12        22.00 ± 0%     17.00 ± 0%  -22.73% (p=0.000 n=10)
CoreWrite/Namespace-12        16.00 ± 0%     13.00 ± 0%  -18.75% (p=0.000 n=10)
CoreWrite/With10_fields-12    1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
CoreWrite/With20_fields-12    1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=10) ¹
CoreWrite/WithNamespace-12    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
geomean                                  ²               -11.42%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

@khushijain21 khushijain21 requested a review from a team June 4, 2024 05:37
@khushijain21 khushijain21 marked this pull request as draft June 4, 2024 06:08
Copy link

codecov bot commented Jun 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.7%. Comparing base (c80e464) to head (c6ab05d).
Report is 7 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #5719     +/-   ##
=======================================
+ Coverage   64.6%   64.7%   +0.1%     
=======================================
  Files        201     201             
  Lines      12587   12626     +39     
=======================================
+ Hits        8134    8173     +39     
  Misses      4216    4216             
  Partials     237     237             
Files Coverage Δ
bridges/otelzap/core.go 90.0% <100.0%> (+<0.1%) ⬆️
bridges/otelzap/encoder.go 87.3% <100.0%> (+1.4%) ⬆️

... and 3 files with indirect coverage changes

@pellared
Copy link
Member

pellared commented Jun 4, 2024

Please make sure to add benchmarks to the PRs which are meant to improve performance.
You can also consider creating separate PRs that would contain just benchmarks.

@khushijain21 khushijain21 marked this pull request as ready for review June 26, 2024 13:35
@@ -196,15 +230,13 @@ type arrayEncoder struct {
}

func (a *arrayEncoder) AppendArray(v zapcore.ArrayMarshaler) error {
// TODO: Use arrayEncoder from a pool.
Copy link
Contributor Author

@khushijain21 khushijain21 Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding sync.pool here does not improve performance

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What benchmark was used to see this?

Copy link
Contributor Author

@khushijain21 khushijain21 Jul 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not entirely sure why, but using pool in AppendArray and AppendObject seems to be causing shared memory issue. I visualised one of the failures with nested cases. For now, I avoid using pool for AppendArray and AppendObject.

This behaviour is not seen outside of this.

Capture3

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At quick glance, I think that the issue is caused by the fact that in array encoder free function does:

arr.elems = arr.elems[:0]

which causes to reuse the same underlying array. The next ArrayAppender is going to access the same elements when doing

err := v.MarshalLogArray(arr)

before the logs are emitted

I suggest not using the pooled encoder for AppendArray and AppendObject in scope of this PR.

I think (hope) that AppendArray and AppendObject are not going to be frequently invoked/used by the bridge users.

Copy link
Member

@pellared pellared Jul 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the same problem with using shared memory applies for AddArray and AddObject. Similarly to #5879.

Probably we miss some unit test that would detect it.

@pellared
Copy link
Member

Please use https://pkg.go.dev/golang.org/x/perf/cmd/benchstat to show the performance improvement (between main and this branch) in the PR description.

@khushijain21 khushijain21 marked this pull request as draft June 27, 2024 07:13
@khushijain21 khushijain21 marked this pull request as ready for review July 4, 2024 16:58
@khushijain21 khushijain21 requested a review from MrAlias July 9, 2024 04:02
@khushijain21
Copy link
Contributor Author

@pellared

@pellared pellared added Skip Changelog Allow PR to succeed without requiring an addition to the CHANGELOG bridge: zap Related to the zap bridge labels Jul 9, 2024
func getArrayEncoder() (arr *arrayEncoder, free func()) {
arr = arrayEncoderPool.Get().(*arrayEncoder)
return arr, func() {
arr.elems = arr.elems[:0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this comment?

// TODO: limit returned size so the pool doesn't hold on to very large
// buffers. Idea is based on
// https://cs.opensource.google/go/x/exp/+/814bf88c:slog/internal/buffer/buffer.go;l=27-34

func getObjectEncoder() (obj *objectEncoder, free func()) {
obj = objectEncoderPool.Get().(*objectEncoder)
return obj, func() {
obj.root.attrs = obj.root.attrs[:0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this comment?

// TODO: limit returned size so the pool doesn't hold on to very large
// buffers. Idea is based on
// https://cs.opensource.google/go/x/exp/+/814bf88c:slog/internal/buffer/buffer.go;l=27-34

@pellared
Copy link
Member

pellared commented Jul 9, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bridge: zap Related to the zap bridge Skip Changelog Allow PR to succeed without requiring an addition to the CHANGELOG
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants