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

Improve migration perf #99773

Merged
merged 9 commits into from
May 17, 2021
Merged

Conversation

mshustov
Copy link
Contributor

@mshustov mshustov commented May 11, 2021

Summary

Part of #92933
While working on SO migrations I noticed a couple of low-hanging fruits improving migration performance.
Testing performed on https://github.com/elastic/kibana/blob/master/src/core/server/saved_objects/migrationsv2/integration_tests/archives/7.7.2_xpack_100k_obj.zip data set as we needed any reproducible source of a large number of SO.
Most of the time Kibana spends on transforming SO POJO (considering I run the test locally with the minimal network overhead) so I removed a few expensive operations:

  • SavedObjectMigrationContext is created once and frozen instead of being created for every SO object
  • do not clone State on every model call. State shouldn't be mutated during migration by design. See the discussion below Improve migration perf #99773 (comment)

It allowed Kibana to reduce migration time for the 100k test data set by ~16% from 99.6sec to 83.536sec.

Checklist

@mshustov mshustov added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v8.0.0 release_note:skip Skip the PR/issue when compiling release notes v7.14.0 labels May 11, 2021
@mshustov mshustov requested review from a team as code owners May 11, 2021 10:52
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-core (Team:Core)

@mshustov mshustov marked this pull request as draft May 11, 2021 10:52
let stateP: State = cloneDeep(currentState);
let stateP: State = currentState;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure our state workflow is pure enough for this to not have any side effect? (should be but still asking)

Copy link
Member

Choose a reason for hiding this comment

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

This might be a red herring:

https://github.com/elastic/kibana/blob/master/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.ts#L50

We are risking that any step might call stateP.logs.push(). So far, I found that we are using everywhere stateP.logs = [...stateP.logs, {...}], so we should be fine...

Copy link
Contributor Author

@mshustov mshustov May 11, 2021

Choose a reason for hiding this comment

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

Are we sure our state workflow is pure enough for this to not have any side effect? (should be but still asking)

@pgayvallet I'm not quite sure cloneDeep usage is justified here.
Mutations made during model execution will be returned from the model and State will be cloned with mutations during the next model call.
The only difference is the OldState mutation won't affect NewState shape. But AFAIK SavedObjectMigrationFn is the only valid case for mutations and we already clone the doc during migrateAndConvert call.


I'm fine to roll back the change. In this case, we will pay the penalty of deep cloning all the SO several times. Plus additional work for GC.

We are risking that any step might call stateP.logs.push()

@afharo Can stateP.logs.push be called with the current implementation? I think so. stateP.logs is not an immutable array, State is not frozen object (not sure why, btw)

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not quite sure cloneDeep usage is justified here.

After a quick look, I don't think either. Also we're supposed to have unit tests covering these things, so I think we're fine keeping the change.

@@ -370,7 +370,7 @@ export interface LegacyDeleteState extends LegacyBaseState {
readonly controlState: 'LEGACY_DELETE';
}

export type State =
export type State = Readonly<
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note: It's not RecursiveReadonly<...> but we can add it to make sure State is not mutated

@@ -24,7 +23,7 @@ export interface SavedObjectAttributesAndReferences {
}

const isPre730Panel = (panel: Record<string, string>): boolean => {
return 'version' in panel ? semverSatisfies(panel.version, '<7.3') : true;
return 'version' in panel ? Semver.gt('7.3.0', panel.version) : true;
Copy link
Contributor Author

@mshustov mshustov May 11, 2021

Choose a reason for hiding this comment

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

noticed that migration spent about 7.4sec here, with these changes, migration is 0.3sec. There are other semverSatisfies usages in dashboard plugin, so it's up to code-owners whether to refactor all the remaining places.

before:
Screenshot 2021-05-11 at 14 55 09

after:
Screenshot 2021-05-11 at 14 50 37

Copy link
Contributor

Choose a reason for hiding this comment

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

Not surprising given that <7.3 needed to be parsed and interpreted.

@mshustov mshustov marked this pull request as ready for review May 11, 2021 17:23
Copy link
Contributor

@ThomThomson ThomThomson left a comment

Choose a reason for hiding this comment

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

Presentation team changes LGTM - Code only review

Copy link
Member

@afharo afharo left a comment

Choose a reason for hiding this comment

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

LGTM

@mshustov
Copy link
Contributor Author

@elasticmachine merge upstream

@mshustov mshustov requested a review from pgayvallet May 14, 2021 09:59
@mshustov
Copy link
Contributor Author

@elasticmachine merge upstream

@mshustov mshustov enabled auto-merge (squash) May 17, 2021 07:54
@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
dashboard 190 217 +27

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
dashboard 138.7KB 138.7KB +1.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
dashboard 313.1KB 324.9KB +11.8KB
Unknown metric groups

References to deprecated APIs

id before after diff
canvas 29 25 -4
crossClusterReplication 8 6 -2
fleet 22 20 -2
globalSearch 4 2 -2
indexManagement 12 7 -5
infra 261 149 -112
lens 67 45 -22
licensing 18 15 -3
maps 286 208 -78
ml 121 115 -6
monitoring 109 56 -53
stackAlerts 101 95 -6
total -295

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@mshustov mshustov merged commit d8a2f8f into elastic:master May 17, 2021
@mshustov mshustov deleted the improve-migration-perf branch May 17, 2021 12:52
mshustov added a commit to mshustov/kibana that referenced this pull request May 18, 2021
* Do not clone state, use TypeCheck it's not mutated

* do not recreate context for every migration

* use more optional semver check

* update SavedObjectMigrationContext type

* add a test model returns new state object

* update docs

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
mshustov added a commit that referenced this pull request May 18, 2021
* Do not clone state, use TypeCheck it's not mutated

* do not recreate context for every migration

* use more optional semver check

* update SavedObjectMigrationContext type

* add a test model returns new state object

* update docs

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
yctercero pushed a commit to yctercero/kibana that referenced this pull request May 25, 2021
* Do not clone state, use TypeCheck it's not mutated

* do not recreate context for every migration

* use more optional semver check

* update SavedObjectMigrationContext type

* add a test model returns new state object

* update docs

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.14.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants