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

tracer: WithHeaderTags performance improvements #2117

Merged
merged 9 commits into from
Jul 18, 2023

Conversation

ajgajg1134
Copy link
Contributor

@ajgajg1134 ajgajg1134 commented Jul 17, 2023

What does this PR do?

Instead of looping over every request header, loop over the configured header->tag map so that performance is not affected when this feature is not in use (and this should also be faster for users of this feature).

Motivation

Previously, we iterated over every http header and called strings.Lower on every single one, this incurred additional CPU cost, especially for services with many http headers in their traced requests, even for users who are not using the "WithHeaderTags" functionality.

Describe how to test/QA your changes

This should be a refactor of customer facing functionality, this is thoroughly covered by the existing unit tests and there is a new benchmark to ensure we don't regress in the future (can be added to benchmarking platform after merging to main)

Reviewer's Checklist

  • Changed code has unit tests for its functionality.
  • If this interacts with the agent in a new way, a system test has been added.

Sorry, something went wrong.

@ajgajg1134 ajgajg1134 changed the base branch from main to release-v1.53.x July 17, 2023 19:40
@pr-commenter
Copy link

pr-commenter bot commented Jul 17, 2023

Benchmarks

Benchmark execution time: 2023-07-18 17:04:41

Comparing candidate commit aef95ea in PR branch andrew.glaude/WithHeaderTagsPerf with baseline commit fecca88 in branch release-v1.53.x.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 27 metrics, 0 unstable metrics.

Verified

This commit was signed with the committer’s verified signature. The key has been revoked.
joachifm Joachim F.
Refactor to use generics and add a type alias for clarity
@ajgajg1134 ajgajg1134 force-pushed the andrew.glaude/WithHeaderTagsPerf branch from 2085373 to 33b7fee Compare July 18, 2023 13:27

Verified

This commit was signed with the committer’s verified signature. The key has been revoked.
joachifm Joachim F.
… headers"

This reverts commit 33b7fee.

Verified

This commit was signed with the committer’s verified signature. The key has been revoked.
joachifm Joachim F.

Verified

This commit was signed with the committer’s verified signature. The key has been revoked.
joachifm Joachim F.
@ajgajg1134
Copy link
Contributor Author

Bench results of withoutFix vs WithFix shows a measurable ~4% improvement. For users with more http headers in their requests (likely most customers, but this is a guess), this improvement will be larger.

goos: darwin
goarch: arm64
pkg: gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http
                  │ withoutFix.bench │           withFix.bench            │
                  │      sec/op      │   sec/op     vs base               │
HttpServeTrace-10        5.585µ ± 6%   5.351µ ± 4%  -4.18% (p=0.002 n=10)

                  │ withoutFix.bench │            withFix.bench            │
                  │       B/op       │     B/op      vs base               │
HttpServeTrace-10       6.157Ki ± 0%   6.198Ki ± 0%  +0.67% (p=0.000 n=10)

                  │ withoutFix.bench │           withFix.bench           │
                  │    allocs/op     │ allocs/op   vs base               │
HttpServeTrace-10         79.00 ± 0%   77.00 ± 0%  -2.53% (p=0.000 n=10)

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@ajgajg1134 ajgajg1134 changed the title Andrew.glaude/with header tags perf tracer: WithHeaderTags performance improvements Jul 18, 2023
@ajgajg1134 ajgajg1134 marked this pull request as ready for review July 18, 2023 15:45
@ajgajg1134 ajgajg1134 requested a review from a team July 18, 2023 15:45
@ajgajg1134 ajgajg1134 requested a review from a team as a code owner July 18, 2023 15:45
Comment on lines 34 to 36
func (r *ReadOnlyLockMap) Clear() {
panic("Not safe to call Clear on a ReadOnlyLockMap")
}
Copy link
Contributor

@knusbaum knusbaum Jul 18, 2023

Choose a reason for hiding this comment

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

🤔 I'm usually not a fan of types that pretend to implement an interface.

Do we need an interface at all? Is there harm in just having a single LockMap struct type that implements all of these? The performance hit from an uncontested rlock should be trivial.

Alternatively, if we think it's really important, I'd rather have a ROMap interface that only specifies Iter and Len. Then the contribs can use that type, and both the ReadOnlyLockMap with Clear() removed (and probably renamed to ReadOnlyMap) and the globalconfig.headerTagMap will satisfy that interface. globalconfig can just continue to use the headerTagMap and its Clear method directly.

@ajgajg1134
Copy link
Contributor Author

With latest changes the bench is even better (nearly 6% vs 4% previously):

goos: darwin
goarch: arm64
pkg: gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http
                  │ withoutFix.bench │           withFix2.bench            │
                  │      sec/op      │    sec/op     vs base               │
HttpServeTrace-10        5.585µ ± 6%   5.253µ ± 22%  -5.94% (p=0.023 n=10)

                  │ withoutFix.bench │           withFix2.bench            │
                  │       B/op       │     B/op      vs base               │
HttpServeTrace-10       6.157Ki ± 0%   6.072Ki ± 0%  -1.38% (p=0.000 n=10)

                  │ withoutFix.bench │          withFix2.bench           │
                  │    allocs/op     │ allocs/op   vs base               │
HttpServeTrace-10         79.00 ± 0%   73.00 ± 0%  -7.59% (p=0.000 n=10)

@ajgajg1134 ajgajg1134 force-pushed the andrew.glaude/WithHeaderTagsPerf branch from aef95ea to b84fd3b Compare July 18, 2023 17:05
Copy link
Contributor

@knusbaum knusbaum left a comment

Choose a reason for hiding this comment

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

Looks great.


// LockMap uses an RWMutex to synchronize map access to allow for concurrent access.
// This should not be used for cases with heavy write load and performance concerns.
type LockMap struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

@ajgajg1134 ajgajg1134 merged commit ac23d5a into release-v1.53.x Jul 18, 2023
@ajgajg1134 ajgajg1134 deleted the andrew.glaude/WithHeaderTagsPerf branch July 18, 2023 19:00
knusbaum pushed a commit that referenced this pull request Jul 19, 2023
…cherrypick #2117) (#2125)

Previously, we iterated over every http header and called strings.Lower
on every single one, this incurred additional CPU cost, especially for
services with many http headers in their traced requests, even for users
who are not using the "WithHeaderTags" functionality.

Instead of looping over every request header, loop over the configured
header->tag map so that performance is not affected when this feature is
not in use (and this should also be faster for users of this feature).

This should be a refactor of customer facing functionality, this is
thoroughly covered by the existing unit tests and there is a new
benchmark to ensure we don't regress in the future (can be added to
benchmarking platform after merging to main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants