-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
add a performance benchmark test for the Buffer implementation #5474
Conversation
Signed-off-by: Brian Pane <[email protected]>
Signed-off-by: Brian Pane <[email protected]>
… drain cases Signed-off-by: Brian Pane <[email protected]>
@jmarantz are there any other changes needed in this before it's commit-worthy? For what it's worth, I've been using this PR in its current form while iterating on my buffer rewrite, and it has been quite effective at detecting regressions so far. |
@alyssawilk can you take a look as (a) senior committer and (b) someone who knows where the performance gotchas might be around buffer code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just a couple of thoughts on my end:
|
||
// On each iteration of the benchmark, add N bytes and drain a multiple of N, as specified | ||
// by DrainCycleRatios. This exercises full-slice, partial-slice, and multi-slice code paths | ||
// in the Buffer's drain implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thoughts around this one is that I think it covers the behaviors you mentioned but I can imagine implementations where it might not tickle perf bugs.
I've seen a bunch of classes where resizing got super inefficient when you cross some arbitrary threshhold (usually powers of 2 but YNK) due to high-low resizing issues. Do you think it might be worthwhile to have an add/remove test which added/removed a large number of "random" (fixed seed for reproducability but try many values tested within a benchmark) adds and drains to make sure there aren't expensive spurious copies / allocations as we add and remove data?
The common case for proxying is we're getting random header and body chunks from the network and parsing some subset as we pass things through the chain, so I think it'd be useful for the tests here and below. Before you do any work I'd be interested in @jmarantz thoughts on useful vs overkill as I think he does more perf testing than I.
// by DrainCycleRatios. This exercises full-slice, partial-slice, and multi-slice code paths | ||
// in the Buffer's drain implementation. | ||
constexpr size_t DrainCycleSize = 7; | ||
constexpr double DrainCycleRatios[DrainCycleSize] = {0.0, 1.5, 1, 1.5, 0, 2.0, 1.0}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd definitely like to see trickle-add and trickle-drain tests added - add one byte at a time many many times, remove one byte at a time many many times. Should be easy enough and while I hope we never have a buffer impl that sucks for those trivial use cases I think it's worth covering :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me. Currently, the BufferMovePartial
test exercises the moving of a byte at a time from one buffer to another, which happens to exercise the add/drain code paths today but might not in the future (if we ever add reference-counting to do zero-copy moves between buffers, for example). So I'll add benchmark tests that directly exercise 1-byte adds and drains.
BENCHMARK(BufferSearchPartialMatch)->Arg(1)->Arg(4096)->Arg(16384)->Arg(65536); | ||
|
||
} // namespace Envoy | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like there are some functions we're not testing which are in upstream envoy. linearize, prepend etc. They're not in the common path but it'd be good to still cover them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm having a little trouble understanding github's comment history, but can you update the PR description to include stats from your new tests, you haven't already done that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I added the latest benchmark output to the PR description.
Signed-off-by: Brian Pane <[email protected]>
Signed-off-by: Brian Pane <[email protected]>
Thanks. It's surprising that BufferMovePartial/65536 takes 2ms but this is the existing condition, and maybe your new impl will improve it :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, that's all I can think of. Hopefully between the two of us we got it all :-P
Josh, haven't seen your LGTM on the latest so I'll let you merge if you're happy with the updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm -- just waiting for CI to finish.
…proxy#5474) * add a performance benchmark test for the Buffer implementation Signed-off-by: Brian Pane <[email protected]> Signed-off-by: Fred Douglas <[email protected]>
Description:
Add a benchmark test for the commonly used operations in the
Buffer
implementation.Risk Level: low
Testing:
Test output:
Docs Changes: N/A
Release Notes: N/A
Related Issues: #4952
Related Pull Requests: 5441
Signed-off-by: Brian Pane [email protected]