-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Faster filtering for unavailable indices #78544
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
Changes from 1 commit
fd23d54
c483e4d
3b10fa2
af276f1
734a7ad
b4237b4
f9a2c88
4268c27
90c1b00
69f56c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -129,7 +129,7 @@ ResolvedIndices resolveIndicesAndAliases(String action, IndicesRequest indicesRe | |||||||||||||
| final boolean replaceWildcards = indicesOptions.expandWildcardsOpen() || indicesOptions.expandWildcardsClosed(); | ||||||||||||||
|
|
||||||||||||||
| // check for all and return list of authorized indices | ||||||||||||||
| if (IndexNameExpressionResolver.isAllIndices(indicesList(indicesRequest.indices()))) { | ||||||||||||||
| if (isAllIndices(indicesRequest.indices())) { | ||||||||||||||
| if (replaceWildcards) { | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you realized that the lone
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I didn't realise that. Thanks for raising it. I was relying on the tests to catch any inconsistent behaviour and it seems we have some test gap. I did some more digging and found there are behaviour differences:
The difference is about how
Based on the following comment, it seems that core is not fully convinced with its own behaviour either. Lines 218 to 223 in eeb09f0
That said, behaviour change is what I tried to avoid and it is the reason why I bothered to add special handling for error message. I'll make some adjustments. Thanks again for noticing it. |
||||||||||||||
| for (String authorizedIndex : authorizedIndices) { | ||||||||||||||
| if (IndexAbstractionResolver.isIndexVisible("*", authorizedIndex, indicesOptions, metadata, nameExpressionResolver, | ||||||||||||||
|
|
@@ -244,6 +244,11 @@ ResolvedIndices resolveIndicesAndAliases(String action, IndicesRequest indicesRe | |||||||||||||
| return resolvedIndicesBuilder.build(); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| static boolean isAllIndices(String[] names) { | ||||||||||||||
| return names == null || names.length == 0 | ||||||||||||||
| || (names.length == 1 && (Metadata.ALL.equals(names[0]) || Regex.isMatchAllPattern(names[0]))); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /** | ||||||||||||||
| * Special handling of the value to authorize for a put mapping request. Dynamic put mapping | ||||||||||||||
| * requests use a concrete index, but we allow permissions to be defined on aliases so if the | ||||||||||||||
|
|
||||||||||||||
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.
For ~10K indices, this change makes the method about 1-2 ms faster (~12ms vs ~10ms). This mostly helps requests that are directly created for REST level requests, e.g.
SearchRequest.Currently, the index authorization for
SearchRequestwith ~10k indices takes about 22ms and its divided as:So a 2ms reduction is close to 10% performance gain.
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 thought about making the change in
IndexNameExpressionResolver.isAllIndices. But it has a test that specifically make surefalseis returned for*... Not sure whether that is still necessary. Anyway, limiting the change to where it is used is safer.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.
It is surprising to me that not converting an empty array to an empty list saves 2 ms, while building a List of 10k elements takes 10 ms.
Or instead of the array->list conversion, it is the fact that
*is handled here rather thanindexAbstractionResolver.resolveIndexAbstractions? They have the same code, so I don't understand it either.I might be missing something.
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.
Sorry for the confusion. I should have given more context in my initial comment. The time saving is observed for a specific field caps query during benckmarking tests:
The option
ignore_unavailable=trueis critical here because that means the following code in the else branch will execute:elasticsearch/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java
Lines 152 to 156 in 324996e
If
authorizedIndicesis large,replacedis also large (because it is an expansion of*), this loop and collecting are where the performance differs.Uh oh!
There was an error while loading. Please reload this page.
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.
Should we replace that stream with something more efficient then?
Like:
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.
That's a clever way to avoid list allocation. It does still step through
replaced. So for the case of a single*, I think it is still worthwhile to skip it entirely.Strictly speaking, if every item of the original indices
indicesRequest.indices() contains wildcard, we can safely skip this block of code. But the value of skipping kinda decreases with increase in size of the original indices because it introduces its own loop. So maybe we can combine skipping for single original index and your faster loop to something like (note it usesisSimpleMatchPatterninstead ofisMatchAllPattern`):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.
As the comment there mentions, the
replacedcollection contains authorized indices that match whatever wildcards from the request's index expression plus whatever concrete names the request had, which have been copied over when buildreplaced.The code that you're working on improving now is iterating over the
replacedcollection, after it had been built, and removes the concrete names. But wouldn't it be better if the names were not added to thereplacedcollection in the first place?This is what I ended up proposing in #76540 .
Please take a look, if it works like I tell it works, it should improve over your proposal still since it is avoiding iterating over
replaced.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.
Thanks @albertzaharovits ! I wasn't aware the existence of #76540 ! I think it is definitely a better solution than this PR. I think #76540 looks great by browsing through it. I need take a closer look tomorrow. But I think it is safe to close this one. Thanks again!