Skip to content

stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching#17018

Merged
jmarantz merged 22 commits intoenvoyproxy:mainfrom
jmarantz:stat-name-prefix-match
Jul 9, 2021
Merged

stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching#17018
jmarantz merged 22 commits intoenvoyproxy:mainfrom
jmarantz:stat-name-prefix-match

Conversation

@jmarantz
Copy link
Copy Markdown
Contributor

@jmarantz jmarantz commented Jun 17, 2021

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

jmarantz added 6 commits June 16, 2021 19:47
…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>
@jmarantz
Copy link
Copy Markdown
Contributor Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17018 (comment) was created by @jmarantz.

see: more, trace.

jmarantz added 7 commits June 17, 2021 21:04
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>
@jmarantz jmarantz changed the title WiP stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping. stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping. Jun 20, 2021
@jmarantz jmarantz marked this pull request as ready for review June 20, 2021 18:47
@jmarantz
Copy link
Copy Markdown
Contributor Author

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.

jmarantz added 2 commits June 20, 2021 15:16
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
@jmarantz
Copy link
Copy Markdown
Contributor Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17018 (comment) was created by @jmarantz.

see: more, trace.

@jmarantz jmarantz changed the title stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping. stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching. Jun 21, 2021
@jmarantz jmarantz changed the title stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching. stats: optimize stats-matchers instantiated with "prefix." pattern, to avoid having to do toString() mapping and caching Jun 21, 2021
@alyssawilk
Copy link
Copy Markdown
Contributor

Stephan's out for the end of the week - Yan can you do first pass?

Copy link
Copy Markdown
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

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>
@jmarantz
Copy link
Copy Markdown
Contributor Author

jmarantz commented Jul 2, 2021

@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?

@zuercher
Copy link
Copy Markdown
Member

zuercher commented Jul 6, 2021

@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.

jmarantz added 2 commits July 6, 2021 16:04
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
@jmarantz
Copy link
Copy Markdown
Contributor Author

jmarantz commented Jul 6, 2021

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>
@jmarantz
Copy link
Copy Markdown
Contributor Author

jmarantz commented Jul 7, 2021

/retest

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17018 (comment) was created by @jmarantz.

see: more, trace.


StatsMatcher::FastResult StatsMatcherImpl::fastRejects(StatName stat_name) const {
if (rejectsAll()) {
return FastResult::NoMatch;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can’t this return “rejects”?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

jmarantz added 2 commits July 8, 2021 11:41
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Signed-off-by: Joshua Marantz <jmarantz@google.com>
Copy link
Copy Markdown
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

This lgtm, modulo the test flake.

@jmarantz
Copy link
Copy Markdown
Contributor Author

jmarantz commented Jul 9, 2021

/retest

@repokitteh-read-only
Copy link
Copy Markdown

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #17018 (comment) was created by @jmarantz.

see: more, trace.

@jmarantz jmarantz merged commit dd7bab7 into envoyproxy:main Jul 9, 2021
@jmarantz jmarantz deleted the stat-name-prefix-match branch July 9, 2021 03:19
leyao-daily pushed a commit to leyao-daily/envoy that referenced this pull request Sep 30, 2021
…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>
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.

stats: Optimize stat-matcher rejection by prefix

5 participants