Skip to content
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

utilccl,kvccl: improve performance when checking enterprise features #62498

Merged
merged 2 commits into from
Mar 31, 2021

Conversation

erikgrinaker
Copy link
Contributor

@erikgrinaker erikgrinaker commented Mar 23, 2021

utilccl: cache license decoding

Previously, the utilccl package would decode the license from the the
base64-encoded Protobuf representation in settings every time it was
needed, which was sufficient for its uses. However, recently there's
been a need to check whether enterprise features are enabled in hot
paths (e.g. with follower reads as seen in #62447), making the decoding
cost too great.

This patch adds cluster.Settings.Cache as a shared cache, and uses it
to cache decoded licenses with a private key type.

utilccl,kvccl: add IsEnterpriseEnabled for faster license checks

utilccl.CheckEnterpriseEnabled() is used to check whether a valid
enterprise license exists for a given feature. If no valid license is
found, it returns an error with specific details.

However, kvccl used this function in follower read hot paths, and
instantiating an error when follower reads are unavailable could have
significant overhead -- see e.g. #62447.

This patch adds IsEnterpriseEnabled(), which has the same behavior as
CheckEnterpriseEnabled() but returns a boolean instead. This is
significantly faster since we can avoid instantiating a custom error
each time. kvccl is also updated to use this in hot paths.

Resolves #62489.

Release note: None

@erikgrinaker erikgrinaker self-assigned this Mar 23, 2021
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@erikgrinaker erikgrinaker changed the title utilccl: improve performance when checking enterprise features utilccl,kvccl: improve performance when checking enterprise features Mar 23, 2021
@erikgrinaker erikgrinaker force-pushed the ccl-check-enterprise branch from 5e39dca to a07d92a Compare March 23, 2021 22:42
Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

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

Reviewed 2 of 2 files at r1.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @erikgrinaker, @nvanbenschoten, and @tbg)


pkg/ccl/utilccl/license_check.go, line 67 at r2 (raw file):

// decodeCache is used to cache licenses for decodeCached().
var decodeCache = struct {

Maybe we can put a Cache sync.Map onto *Settings to avoid the singleton (the cache could grow quite a bit in the large packages). The map could be used for similar things in the future as they arise.

You'd use

type licenseCacheKey string

for the key, so different users wouldn't see each other.

@tbg tbg self-requested a review March 24, 2021 14:50
Copy link
Contributor Author

@erikgrinaker erikgrinaker left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @nvanbenschoten and @tbg)


pkg/ccl/utilccl/license_check.go, line 67 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

Maybe we can put a Cache sync.Map onto *Settings to avoid the singleton (the cache could grow quite a bit in the large packages). The map could be used for similar things in the future as they arise.

You'd use

type licenseCacheKey string

for the key, so different users wouldn't see each other.

Wouldn't it be sort of odd to just "bolt on" this field that wasn't really used by the settings themselves? A cleaner approach might be to register encoders/decoders for settings values, but that seems somewhat excessive. Don't have a strong opinion on it though, can try out a field.

Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

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

Reviewed 4 of 4 files at r2.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @erikgrinaker and @nvanbenschoten)


pkg/ccl/utilccl/license_check.go, line 67 at r2 (raw file):

Previously, erikgrinaker (Erik Grinaker) wrote…

Wouldn't it be sort of odd to just "bolt on" this field that wasn't really used by the settings themselves? A cleaner approach might be to register encoders/decoders for settings values, but that seems somewhat excessive. Don't have a strong opinion on it though, can try out a field.

It's a little odd, I agree, but if we're trying to avoid singletons (as I think we should, given that we go through many ephemeral servers in a test package), you need one grab bag of things that gets passed ~everywhere and in our case that, de facto, is *Settings.

@erikgrinaker erikgrinaker force-pushed the ccl-check-enterprise branch from a07d92a to 0487c08 Compare March 24, 2021 22:24
Copy link
Contributor Author

@erikgrinaker erikgrinaker left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @nvanbenschoten and @tbg)


pkg/ccl/utilccl/license_check.go, line 67 at r2 (raw file):

Previously, tbg (Tobias Grieger) wrote…

It's a little odd, I agree, but if we're trying to avoid singletons (as I think we should, given that we go through many ephemeral servers in a test package), you need one grab bag of things that gets passed ~everywhere and in our case that, de facto, is *Settings.

Makes sense, done.

@erikgrinaker erikgrinaker force-pushed the ccl-check-enterprise branch 2 times, most recently from 2978ef0 to 7a005e8 Compare March 24, 2021 23:13
Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

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

Reviewed 3 of 3 files at r3.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @erikgrinaker and @nvanbenschoten)


pkg/ccl/utilccl/license_check.go, line 122 at r3 (raw file):

	if err != nil {
		return 0, err
	} else if license == nil {

isn't the linter yelling at you to write it like

if err != nil {
  return 0, err
}
if license == nil {
  return 0, nil
}

Copy link
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

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

:lgtm:

Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @erikgrinaker and @nvanbenschoten)

`utilccl.CheckEnterpriseEnabled()` is used to check whether a valid
enterprise license exists for a given feature. If no valid license is
found, it returns an error with specific details.

However, `kvccl` used this function in follower read hot paths, and
instantiating an error when follower reads are unavailable could have
significant overhead -- see e.g. cockroachdb#62447.

This patch adds `IsEnterpriseEnabled()`, which has the same behavior as
`CheckEnterpriseEnabled()` but returns a boolean instead. This is
significantly faster since we can avoid instantiating a custom error
each time. `kvccl` is also updated to use this in hot paths.

Release note: None
Previously, the `utilccl` package would decode the license from the the
base64-encoded Protobuf representation in settings every time it was
needed, which was sufficient for its uses. However, recently there's
been a need to check whether enterprise features are enabled in hot
paths (e.g. with follower reads as seen in cockroachdb#62447), making the decoding
cost too great.

This patch adds `cluster.Settings.Cache` as a shared cache, and uses it
to cache decoded licenses with a private key type.

Release note: None
@erikgrinaker erikgrinaker force-pushed the ccl-check-enterprise branch from 7a005e8 to a7c1f37 Compare March 31, 2021 14:55
Copy link
Contributor Author

@erikgrinaker erikgrinaker left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @nvanbenschoten and @tbg)


pkg/ccl/utilccl/license_check.go, line 122 at r3 (raw file):

Previously, tbg (Tobias Grieger) wrote…

isn't the linter yelling at you to write it like

if err != nil {
  return 0, err
}
if license == nil {
  return 0, nil
}

No, but I'll change it anyway. :)

@erikgrinaker
Copy link
Contributor Author

bors=tbg

CI failure is flake, reproducible when stressing on master.

@erikgrinaker
Copy link
Contributor Author

bors r=tbg

@craig
Copy link
Contributor

craig bot commented Mar 31, 2021

Build failed (retrying...):

@craig
Copy link
Contributor

craig bot commented Mar 31, 2021

Build failed:

@tbg
Copy link
Member

tbg commented Mar 31, 2021

bors r+

CI was broken, I think it's since been fixed

@craig craig bot merged commit 36f99c3 into cockroachdb:master Mar 31, 2021
@craig
Copy link
Contributor

craig bot commented Mar 31, 2021

Build succeeded:

@erikgrinaker erikgrinaker deleted the ccl-check-enterprise branch April 9, 2021 13:43
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.

utilccl: improve CheckEnterpriseEnabled performance
3 participants