-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[core.uiSettings] Adds cache for raw settings to boost performance of getAll()
#97070
Conversation
Pinging @elastic/kibana-core (Team:Core) |
I removed this change. |
@@ -143,8 +146,17 @@ export class UiSettingsClient implements IUiSettingsClient { | |||
} | |||
|
|||
private async getRaw(): Promise<UiSettingsRaw> { | |||
const cachedValue = this.rawCache.get(); |
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'm not really happy with 2 levels of caching, but I'd defer to the full refactoring of the UI settings
service to address the problem.
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.
++ Agreed on this, I think the perf benefits make this worth it as an interim solution, but really we should restructure this during a proper refactoring
|
||
await uiSettings.getAll(); | ||
expect(savedObjectsClient.get).toHaveBeenCalledTimes(1); | ||
expect(lodashDefaultsDeep).toHaveBeenCalledTimes(1); |
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.
tbh we should test that result of getAll
and arguments of defaultsDeep
cannot be mutated, instead of testing the implementation detail.
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 removed this change. {...obj } creates a shallow copy, as a result, defaultsDeep mutates the nested object
Thanks for catching (and fixing) this! Will update this test as well.
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 haven't run the performance tests on this code, but I don't think this solves the core problem that with the use of lodash. See #75850 for more details, but the most important is that the three-argument version of mergeDeep
is exponentially slower.
const userProvided = await this.getUserProvided(); | ||
return defaultsDeep({}, userProvided, this.defaults); | ||
const result = defaultsDeep({}, userProvided, this.defaults); |
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.
This pattern of using lodash with 3 arguments is exactly what we are trying to avoid. It really must be two arguments.
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.
What pattern do you suggest using when merging two objects into a third one without mutating any of the input objects then?
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.
IMO the best alternative would be don't use defaultsDeep
at all or remove getAll
from the public contract on the server-side (we would reduce the number of js object processed on every get(..)
).
Removing getAll
aligns with our approach of removing implicit dependencies across the plugins. I'd go this way. It requires data
plugin refactoring to provide API to register fieldFormatters
fieldFormatsRegistry.init((key: string) => uiConfigs[key], {}, this.fieldFormatClasses); |
const uiSettingsCache = pick(await uiSettingsClient.getAll(), aggsRequiredUiSettings); |
We can remove getAll
from the client-side public contract as soon as Advanced Settings UI becomes part of Core.
Going to move this back into draft until we can work on a proper solution |
@lukeelmers I added the item to the list of |
@lukeelmers I actually found my old PR improving performance for this logic #85027 |
💛 Build succeeded, but was flaky
Test FailuresKibana Pipeline / general / X-Pack API Integration Tests.x-pack/test/api_integration/apis/security_solution/feature_controls·ts.apis SecuritySolution Endpoints feature controls APIs can't be accessed by user with dashboard "all" privilegesStandard Out
Stack Trace
Metrics [docs]Page load bundle
History
To update your PR or re-run it, just comment with: cc @lukeelmers |
closed in favor of #85027 removing |
Closes #97025
As explained in #75850, the upgrade to lodash 4 resulted in some performance degradations in the
defaultsDeep
method.A few users have noticed some performance issues in Kibana after upgrading to 7.12, and after doing some profiling, @wylieconlon noticed that we could improve the way we use
defaultsDeep
in the ui settings client.This PR makes 2 changes:
defaultsDeep
to pass 2 arguments instead of 3, which provides a slight perf boostdefaultsDeep
, which can boost performance significantly in scenarios where frequent calls togetRaw()
are being made. In Wylie's testing using a complex dashboard, the performance ofgetRaw()
improved by an order of magnitude after a cache was added.