stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching#17018
Conversation
…ock. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…U parity Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
/retest |
|
Retrying Azure Pipelines: |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…ejected by the fast path. Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
Pradeep, can you take a pass through this? Don't hesitate to ping me with any questions, and I'm happy to break this up into 3 layered PRs if you like. |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
/retest |
|
Retrying Azure Pipelines: |
|
Stephan's out for the end of the week - Yan can you do first pass? |
zuercher
left a comment
There was a problem hiding this comment.
Other than some minor nits, the only thing that concerns me here is that the fast/slowRejects interface seems brittle. It's already kind of tricky to see that it's used correctly in the more complex cases.
What do you think about having fastRejects return a result type that's required as input to slowRejects? Something like:
using FastRejectResult = /* some simple struct that contains implements a 'bool rejected()` method. */
virtual FastRejectResult fastRejects(StatName name) const PURE;
virtual bool slowRejects(StatName name, FastRejectResult fast_result) const PURE;
It makes the if fastRejects(name) || slowRejects(name) a little more cumbersome, but maybe we can just have a helper for case?
Signed-off-by: Joshua Marantz <jmarantz@google.com>
…ed by slowRejects() Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
@zuercher I haven't taken care of the nits yet but I have a candidate patch I've committed for using an explicit intermediate state object per your suggestion (mostly). It makes things a quite bit more cumbersome at call-sites but it does make the implementation assumptions more explicit, so this is probably a win. The main problem is that the extra state has to be passed around to a a few different functions in ThreadLocalStore. WDYT? |
|
@jmarantz I agree this is a win: I find it easier to follow and easier to be confident that the fast/slow calls are done correctly. |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
OK ptal; I didn't really change anything from the prior state other than addressing the comment grammar issues and adding comments for the new nested class. One thing I considered was protecting the default ctor of FastResult but it seems pretty cumbersome with mocks. |
Signed-off-by: Joshua Marantz <jmarantz@google.com>
|
/retest |
|
Retrying Azure Pipelines: |
|
|
||
| StatsMatcher::FastResult StatsMatcherImpl::fastRejects(StatName stat_name) const { | ||
| if (rejectsAll()) { | ||
| return FastResult::NoMatch; |
There was a problem hiding this comment.
yes, good catch. that was working before I switched to enums, but there was not a test that discerned the difference between fast-reject and slow-reject of this case. I added a couple of tests for this.
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
zuercher
left a comment
There was a problem hiding this comment.
This lgtm, modulo the test flake.
|
/retest |
|
Retrying Azure Pipelines: |
…o avoid having to do toString() mapping and caching (envoyproxy#17018) Commit Message: Optimizes a useful special-case where we exclude stats by prefix. Ordinarily we must string-match against stringified StatName, and the stringification is both slow and requires a global symbol table lock. To avoid that becoming a performance/contention bottleneck, we keep excluded StatNames in the ThreadLocalStore caches, which can consume a lot of memory at scale. It consumes less than the stats, but it can still be significant. To avoid this problem when matching with a full token prefix, we can do the exclusion comparison without converting to a string. This is fast and doesn't require taking any locks, so we don't need to save excluded StatNames in a map. This is both faster and provides a significant reduction in memory. Additional Description: Risk Level: medium -- this adds some complexity to the StatsMatcher implementation Testing: //test/... plus new performance tests, and targeted unit tests to hit corner cases Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Fixes: envoyproxy#17027 Signed-off-by: Joshua Marantz <jmarantz@google.com>
Commit Message: Optimizes a useful special-case where we exclude stats by prefix. Ordinarily we must string-match against stringified StatName, and the stringification is both slow and requires a global symbol table lock. To avoid that becoming a performance/contention bottleneck, we keep excluded StatNames in the ThreadLocalStore caches, which can consume a lot of memory at scale. It consumes less than the stats, but it can still be significant.
To avoid this problem when matching with a full token prefix, we can do the exclusion comparison without converting to a string. This is fast and doesn't require taking any locks, so we don't need to save excluded StatNames in a map.
This is both faster and provides a significant reduction in memory.
Additional Description:
Risk Level: medium -- this adds some complexity to the StatsMatcher implementation
Testing: //test/... plus new performance tests, and targeted unit tests to hit corner cases
Docs Changes: n/a
Release Notes: n/a
Platform Specific Features: n/a
Fixes: #17027