-
Notifications
You must be signed in to change notification settings - Fork 40.9k
feat: optimize ListAll and ListAllByNamespace to return directly when nothing to select #132255
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
feat: optimize ListAll and ListAllByNamespace to return directly when nothing to select #132255
Conversation
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the The Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
@liggitt kindly ping, can you pls help to review this pr, thanks |
selector := labels.SelectorFromSet(label) | ||
var selector labels.Selector | ||
if label == nil { | ||
selector = labels.Nothing() |
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.
everywhere else, an empty labels map selects everything ...
// SelectorFromSet returns a Selector which will match exactly the given Set. A
// nil Set is considered equivalent to Everything().
func SelectorFromSet(ls Set) Selector {
making this switch so that an empty set selects nothing is really confusing and kind of breaking
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.
not exactly
e.g.
func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) { | |
if ps == nil { | |
return labels.Nothing(), nil | |
} | |
if len(ps.MatchLabels)+len(ps.MatchExpressions) == 0 { | |
return labels.Everything(), nil | |
} |
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.
a nil *LabelSelector
means "match nothing"
an nil map[string]string
label selector means "match everything"
@@ -32,6 +32,10 @@ type AppendFunc func(interface{}) | |||
|
|||
// ListAll lists items in the store matching the given selector, calling appendFn on each one. | |||
func ListAll(store Store, selector labels.Selector, appendFn AppendFunc) error { | |||
if selector == labels.Nothing() { |
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.
Comparing an interface instance to a concrete value to determine if it is the special-case "match nothing" is a bit odd. I'm not sure whether it is better to add a new method to the labels.Selector interface so implementations can identify this case, or add a helper func MatchesNothing(selector labels.Selector) bool
function to the labels package so we can keep the special comparison to the nothingSelector
type local to the package.
cc @deads2k for an opinion
cc @munnerz who has spent some time thinking about optimizing / canonicalizing selectors (so something like matchExpressions: [{"key":"foo","operator":"Exists"}, {"key":"foo","operator":"DoesNotExist"}]
would also correctly identify as matching nothing)
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.
External callers might also need to check whether the selector is labels.Nothing(). Would it be ok to add a new function to the interface, similar to Empty()?
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 prefer func MatchesNothing(selector labels.Selector)
with an implementation we can improve over time.
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.
Thank you all for the code review. The helper function has been added.
22bb2e4
to
01296b1
Compare
01296b1
to
e8405e5
Compare
…n nothing to select Signed-off-by: likakuli <[email protected]>
e8405e5
to
5a7e04b
Compare
/lgtm |
LGTM label has been added. Git tree hash: 4124880b87ebe0f64250252dee71eadc7c199f63
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: liggitt, likakuli The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
What type of PR is this?
/kind feature
What this PR does / why we need it:
The
ListAll
andListAllByNamespace
methods of the lister still perform a full (but ineffective) iteration even when the passed-in selector is labels.Nothing(). While it's possible to add a check at the call site to skip the operation when the selector is labels.Nothing(), this relies on developers to remember to do so, making it easy to miss such checks.e.g.
kubernetes/pkg/scheduler/framework/types.go
Lines 662 to 675 in 990e5de
nsSelector
will belabels.Nothing()
ifterm.NamespaceSelector
is nil.kubernetes/pkg/scheduler/framework/plugins/interpodaffinity/plugin.go
Lines 123 to 136 in 990e5de
at.NamespaceSelector
is thensSelector
mentioned above. So when it islabels.Nothing()
, it results in an unnecessary iteration over all namespaces when to callList
function.Which issue(s) this PR is related to:
Special notes for your reviewer:
Does this PR introduce a user-facing change?
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: