Skip to content

Optimize trait loop evaluation#19097

Merged
vitorenesduarte merged 20 commits intomasterfrom
vitor/traits-to-roles-regexp-precompile
Dec 7, 2022
Merged

Optimize trait loop evaluation#19097
vitorenesduarte merged 20 commits intomasterfrom
vitor/traits-to-roles-regexp-precompile

Conversation

@vitorenesduarte
Copy link
Copy Markdown
Contributor

@vitorenesduarte vitorenesduarte commented Dec 6, 2022

Fixes #18973.

This PR reduces the number of log.Debugs in the trait loop evaluation in case of a mismatch.

This PR also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.

Testing

None, besides the existing/updated unit tests.

Benchmark

# master branch
go test -run='^$' -bench=^BenchmarkTraitToRoles$ github.com/gravitational/teleport/lib/services -count=5 > master_bench
go test -v -run='^$' -bench=^BenchmarkTraitToRoles$ github.com/gravitational/teleport/lib/services -count=5 > master_bench_verbose

# this PR
go test -run='^$' -bench=^BenchmarkTraitToRoles$ github.com/gravitational/teleport/lib/services -count=5 > pr_bench
go test -v -run='^$' -bench=^BenchmarkTraitToRoles$ github.com/gravitational/teleport/lib/services -count=5 > pr_bench_verbose
  • go test:
❯ benchstat master_bench pr_bench
name                                                                                    old time/op  new time/op  delta
TraitToRoles/no_mappings_no_match-10                                                    2.99ns ± 0%  3.05ns ± 0%   +2.13%  (p=0.008 n=5+5)
TraitToRoles/simple_mappings_no_match-10                                                64.7ns ± 0%  64.6ns ± 0%     ~     (p=0.841 n=5+5)
TraitToRoles/simple_mappings_no_value_match-10                                          11.3µs ± 0%  12.0µs ± 0%   +6.36%  (p=0.008 n=5+5)
TraitToRoles/simple_mappings_direct_admin_value_match-10                                18.7µs ± 0%  12.7µs ± 0%  -32.43%  (p=0.008 n=5+5)
TraitToRoles/simple_mappings_direct_user_value_match-10                                 11.7µs ± 1%  11.6µs ± 0%     ~     (p=0.095 n=5+5)
TraitToRoles/simple_mappings_direct_user_value_match_with_array-10                      11.7µs ± 0%  11.6µs ± 0%   -1.11%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_no_match-10                                          33.4ns ± 0%  33.4ns ± 0%     ~     (p=0.667 n=5+4)
TraitToRoles/regexp_mappings_match_no_match_-_subprefix-10                              6.70µs ± 0%  6.99µs ± 0%   +4.36%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_value_with_capture_match-10                          16.1µs ± 0%   8.7µs ± 0%  -46.22%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_multiple_value_with_capture_match,_deduplication-10  32.2µs ± 0%  10.2µs ± 0%  -68.22%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_first_matches,_second_does_not-10                    23.3µs ± 1%  12.1µs ± 0%  -48.22%  (p=0.008 n=5+5)
TraitToRoles/regexp_compilation_invalid_regexp-10                                       36.9µs ± 1%  20.2µs ± 0%  -45.33%  (p=0.008 n=5+5)
TraitToRoles/regexp_compilation_regexp_are_not_compiled_if_not_needed-10                28.6ns ± 0%  28.6ns ± 0%     ~     (p=0.571 n=4+5)
TraitToRoles/empty_expands_are_skipped_value_with_capture_match-10                      12.2µs ± 0%   8.2µs ± 1%  -32.93%  (p=0.008 n=5+5)
TraitToRoles/glob_wildcard_match_empty_value_match-10                                   5.29µs ± 0%  5.07µs ± 0%   -4.14%  (p=0.008 n=5+5)
TraitToRoles/glob_wildcard_match_any_value_match-10                                     5.47µs ± 1%  5.20µs ± 0%   -4.85%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_multiple_groups-10                                102µs ± 1%    61µs ± 1%  -40.06%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_one_group-10                                     42.1µs ± 0%  42.3µs ± 0%   +0.53%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_one_group_with_multiple_roles-10                 57.5µs ± 1%  44.6µs ± 0%  -22.39%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_No_match_only_due_to_case-sensitivity-10                 45.3µs ± 1%  45.2µs ± 1%     ~     (p=0.690 n=5+5)
  • go test -v:
❯ benchstat master_bench_verbose pr_bench_verbose
name                                                                                    old time/op  new time/op  delta
TraitToRoles/no_mappings_no_match-10                                                    2.99ns ± 0%  3.05ns ± 0%   +2.11%  (p=0.008 n=5+5)
TraitToRoles/simple_mappings_no_match-10                                                64.6ns ± 0%  64.7ns ± 0%     ~     (p=0.429 n=5+5)
TraitToRoles/simple_mappings_no_value_match-10                                          34.3µs ± 2%  35.2µs ± 4%     ~     (p=0.056 n=5+5)
TraitToRoles/simple_mappings_direct_admin_value_match-10                                31.6µs ± 1%  25.4µs ± 1%  -19.81%  (p=0.008 n=5+5)
TraitToRoles/simple_mappings_direct_user_value_match-10                                 23.9µs ± 1%  24.2µs ± 2%   +1.19%  (p=0.016 n=5+5)
TraitToRoles/simple_mappings_direct_user_value_match_with_array-10                      23.9µs ± 2%  24.1µs ± 0%     ~     (p=0.222 n=5+5)
TraitToRoles/regexp_mappings_match_no_match-10                                          33.7ns ± 1%  33.4ns ± 0%     ~     (p=0.190 n=5+4)
TraitToRoles/regexp_mappings_match_no_match_-_subprefix-10                              19.1µs ± 0%  19.4µs ± 1%   +1.52%  (p=0.016 n=4+5)
TraitToRoles/regexp_mappings_match_value_with_capture_match-10                          15.9µs ± 1%   8.6µs ± 0%  -45.93%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_multiple_value_with_capture_match,_deduplication-10  32.0µs ± 0%  10.2µs ± 0%  -68.04%  (p=0.008 n=5+5)
TraitToRoles/regexp_mappings_match_first_matches,_second_does_not-10                    36.9µs ± 1%  24.7µs ± 1%  -33.04%  (p=0.008 n=5+5)
TraitToRoles/regexp_compilation_invalid_regexp-10                                       50.9µs ± 1%  32.8µs ± 2%  -35.46%  (p=0.008 n=5+5)
TraitToRoles/regexp_compilation_regexp_are_not_compiled_if_not_needed-10                28.6ns ± 0%  28.6ns ± 0%     ~     (p=0.143 n=5+4)
TraitToRoles/empty_expands_are_skipped_value_with_capture_match-10                      12.1µs ± 1%   8.1µs ± 0%  -33.23%  (p=0.008 n=5+5)
TraitToRoles/glob_wildcard_match_empty_value_match-10                                   5.28µs ± 0%  5.05µs ± 0%   -4.38%  (p=0.008 n=5+5)
TraitToRoles/glob_wildcard_match_any_value_match-10                                     5.47µs ± 1%  5.19µs ± 0%   -5.06%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_multiple_groups-10                                180µs ± 2%   111µs ± 1%  -38.22%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_one_group-10                                     79.6µs ± 2%  79.4µs ± 1%     ~     (p=1.000 n=5+5)
TraitToRoles/Whitespace/dashes_Matches_one_group_with_multiple_roles-10                 96.6µs ± 1%  81.1µs ± 1%  -16.03%  (p=0.008 n=5+5)
TraitToRoles/Whitespace/dashes_No_match_only_due_to_case-sensitivity-10                 83.7µs ± 2%  82.4µs ± 1%     ~     (p=0.095 n=5+5)

@vitorenesduarte vitorenesduarte self-assigned this Dec 6, 2022
@vitorenesduarte vitorenesduarte changed the title Optimize trait loop evalution Optimize trait loop evaluation Dec 6, 2022
@zmb3
Copy link
Copy Markdown
Collaborator

zmb3 commented Dec 6, 2022

Might be nice to add a benchmark here as well, which would show how much of an improvement this change makes, as well as make it easier to detect performance regressions in the future.

Comment thread lib/services/user_test.go Outdated
Comment thread lib/services/user_test.go Outdated
Comment thread lib/services/user_test.go Outdated
Comment thread lib/services/traits.go Outdated
Comment thread lib/services/traits.go Outdated
@codingllama
Copy link
Copy Markdown
Contributor

Might be nice to add a benchmark here as well, which would show how much of an improvement this change makes, as well as make it easier to detect performance regressions in the future.

+1 , let's get some numbers in. It's hard to assess how well this works just by reading it.

Comment thread lib/services/traits.go Outdated

// warn at most maxMismatchedTraitValuesWarned trait values to prevent huge warning lines
if len(mismatched) > maxMismatchedTraitValuesWarned {
warnings = append(warnings, fmt.Sprintf(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I know I suggested adding this to the returned warnings myself but now that I'm thinking about it again I wonder if we'll only be increasing amount of log noise this way - because these returned warnings are logged at "warn" level on the caller's side. I think we should just log these "mismatched" traits locally in this method and keep it at debug.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I had similar thoughts here. +1.

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.

Done in 15df538.

Copy link
Copy Markdown
Contributor

@codingllama codingllama left a comment

Choose a reason for hiding this comment

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

Code looks reasonable. @vitorenesduarte, could you provide some measurements and maybe add a Go benchmark test, so we have data behind the PR? Other than that, happy to stamp it.

Comment thread lib/services/user_test.go Outdated
}


/*
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's no need to include this comment in the source code, but it would be nice to see a before/after in the PR description. You can use golang.org/x/perf/cmd/benchstat to generate a nice diff.

Copy link
Copy Markdown
Contributor Author

@vitorenesduarte vitorenesduarte Dec 7, 2022

Choose a reason for hiding this comment

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

I saw results like these in other benchmarks. Removed in 7eaa6ea.

Thanks for suggesting benchstat!!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Numbers look great, thanks!

@vitorenesduarte
Copy link
Copy Markdown
Contributor Author

@zmb3 @codingllama ce86dc0 adds a benchmark using the test cases we already had for TestOIDCMapping (this made the PR harder to review though).

I ran the benchmark both with go test and go test -v to try to also account for the log.Debug calls.
The PR description now contains some benchmark results.

@vitorenesduarte vitorenesduarte enabled auto-merge (squash) December 7, 2022 15:51
Comment thread lib/services/user_test.go Outdated
}


/*
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Remove the comment with benchmark results - it's better to run it again if necessary.

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.

Done in 7eaa6ea.

@codingllama
Copy link
Copy Markdown
Contributor

@zmb3 @codingllama ce86dc0 adds a benchmark using the test cases we already had for TestOIDCMapping (this made the PR harder to review though).

I ran the benchmark both with go test and go test -v to try to also account for the log.Debug calls. The PR description now contains some benchmark results.

Many thanks! LGTM.

@github-actions github-actions Bot removed the request for review from GavinFrazar December 7, 2022 19:39
@vitorenesduarte vitorenesduarte merged commit 9819e19 into master Dec 7, 2022
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 7, 2022

@vitorenesduarte See the table below for backport results.

Branch Result
branch/v10 Failed
branch/v11 Create PR
branch/v9 Failed

vitorenesduarte pushed a commit that referenced this pull request Dec 8, 2022
This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.

This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.
@vitorenesduarte vitorenesduarte deleted the vitor/traits-to-roles-regexp-precompile branch December 8, 2022 15:03
vitorenesduarte pushed a commit that referenced this pull request Dec 8, 2022
* Refactor tests under services package.

Refactored all tests under "lib/services/suite" to use testify instead
of gocheck.

* Optimize trait loop evaluation (#19097)

This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.

This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.

Co-authored-by: Russell Jones <rjones@goteleport.com>
vitorenesduarte pushed a commit that referenced this pull request Dec 8, 2022
This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.

This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.
vitorenesduarte pushed a commit that referenced this pull request Dec 9, 2022
* Refactor tests under services package.

Refactored all tests under "lib/services/suite" to use testify instead
of gocheck.

* Optimize trait loop evaluation (#19097)

This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.

This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.

Co-authored-by: Russell Jones <rjones@goteleport.com>
fheinecke pushed a commit that referenced this pull request Dec 16, 2022
* Refactor tests under services package.

Refactored all tests under "lib/services/suite" to use testify instead
of gocheck.

* Optimize trait loop evaluation (#19097)

This commit reduces the number of `log.Debug`s in the trait loop evaluation in case of a mismatch.

This commit also optimizes the trait eval loop ensuring that each regexp is compiled at-most once, and only if strictly needed.

Co-authored-by: Russell Jones <rjones@goteleport.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.

Remove debug log for traits evaluation

4 participants