-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Squash allocations in selector parsing and other hotspots #9564
Conversation
e57d003
to
51d7220
Compare
Reduce usage of WithFields on the hot path; it allocates heavily.
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 left a few questions and nits.
log.Debug("Remaining input: ", input) | ||
} | ||
startLen := len(input) | ||
input = strings.TrimLeft(input, whitespace) | ||
input = trimWhitespace(input) |
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 assume we can do this because of the limited charset we recognise, right? But what's the main motivation 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.
Yes, I think TrimLeft was allocating/doing work to calculate the cut set so this was faster.
) | ||
func (t Token) String() string { | ||
return fmt.Sprintf("%s(%s)", t.Kind, t.Value) | ||
} | ||
|
||
// Tokenize transforms string to token slice | ||
func Tokenize(input string) (tokens []Token, err error) { |
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.
nit: no need for named return values.
if len(input) > 1 && input[1] == '=' { | ||
tokens = append(tokens, Token{TokEq, nil}) | ||
input = input[2:] | ||
if input, found = strings.CutPrefix(input, "=="); found { |
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.
Using CutPrefix
is definitely easier to read. But I wonder why here we move to a cleaner version, while for TrimLeft
the decision is to implement a new function?
/merge-when-ready squash-commits |
OK, I will merge the pull request when it's ready, squash the commits when I merge it, and leave the branch after I've merged it. |
…ico#9564) * Squash some chatty allocations. Reduce usage of WithFields on the hot path; it allocates heavily. * Avoid allocations when validating selectors. * Clean ups in tokenizer. * Tweaks. * Markups.
Description
Noticed that selector parsing was a memory allocation hotspot in clusters with lots of policy. Most of that was down to validating selectors so we were just throwing away the parsed selector.
tokenizer.AppendTokens()
to do tokenization into a pre-allocated buffer. Use a shared instance of the parser to hold the shared token buffer (protected my mutex).strings.Cut
and friends; makes for easier reading and less string slicing.Before:
After:
Related issues/PRs
CORE-10829
Todos
Release Note
Reminder for the reviewer
Make sure that this PR has the correct labels and milestone set.
Every PR needs one
docs-*
label.docs-pr-required
: This change requires a change to the documentation that has not been completed yet.docs-completed
: This change has all necessary documentation completed.docs-not-required
: This change has no user-facing impact and requires no docs.Every PR needs one
release-note-*
label.release-note-required
: This PR has user-facing changes. Most PRs should have this label.release-note-not-required
: This PR has no user-facing changes.Other optional labels:
cherry-pick-candidate
: This PR should be cherry-picked to an earlier release. For bug fixes only.needs-operator-pr
: This PR is related to install and requires a corresponding change to the operator.