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

[node-modules] Improve deduplication efficiency by tracking ancestor dependencies #955

Merged
merged 16 commits into from
Feb 27, 2020

Conversation

larixer
Copy link
Member

@larixer larixer commented Feb 15, 2020

What's the problem this PR addresses?

The deduplication efficiency is still poor both size-wise and performance-wise in master

How did you fix it?

I have rewritten hoisting algorithm to hoist dependencies from the whole tree into current root node to improve performance and added ancestor dependencies tracking to improve deduplication efficiency. This has simplified algorithm in some areas (checks) and sophisticated in another areas (node cloning), but generally it is now far superior than the one used in master both size-wise and performance-wise. It is not yet as perfect as it can be, but it is still a good checkpoint IMO.

@nicolo-ribaudo
Copy link
Contributor

@larixer In babel/babel#11167, the size of all the node_modules folders is 7.8GB, vs ~1GB with Yarn 1 + lerna.

Let me know when I can test this PR!

@larixer
Copy link
Member Author

larixer commented Feb 26, 2020

@nicolo-ribaudo Sure, I will

The difference in size is certainly above what I have expected, I will test on babel repo the deduplication efficiency, since on my repo it was only 18% worser (10% due to native package installation by v2 for the cpu and os variants that are different from current OS and CPU and 8%, due to v1 and npm have bug when they quite often violate peer dependency promise in certain situations)

@nicolo-ribaudo
Copy link
Contributor

nicolo-ribaudo commented Feb 26, 2020

I'm computing the node_modules total size with this command:

du -s node_modules codemods/*/node_modules eslint/*/node_modules packages/*/node_modules | tr -cd '0-9\n' | xargs | tr ' ' '+' | bc

With yarn 1 + lerna I'm getting 1012845KB (989 MB) (this branch), while with yarn 2 master I get 8139216KB (7.76 GB) (this PR).

Detailed sizes
Folder Old size (KB) New size (KB) Delta (new - old)
codemods/babel-plugin-codemod-object-assign-to-object-spread/node_modules 68 99156 99088
codemods/babel-plugin-codemod-optional-catch-binding/node_modules 68 98888 98820
eslint/babel-eslint-parser/node_modules 37476 100 -37376
eslint/babel-eslint-plugin-development/node_modules 36804 6936 -29868
eslint/babel-eslint-plugin/node_modules 37512 0 -37512
eslint/babel-eslint-shared-fixtures/node_modules 112 415932 415820
eslint/babel-eslint-tests/node_modules 45588 0 -45588
node_modules 331928 636152 304224
packages/babel-cli/node_modules 7040 53652 46612
packages/babel-code-frame/node_modules 268 8 -260
packages/babel-compat-data/node_modules 20880 0 -20880
packages/babel-core/node_modules 6548 54040 47492
packages/babel-generator/node_modules 5864 0 -5864
packages/babel-helper-annotate-as-pure/node_modules 8 0 -8
packages/babel-helper-bindify-decorators/node_modules 8 0 -8
packages/babel-helper-builder-binary-assignment-operator-visitor/node_modules 8 0 -8
packages/babel-helper-builder-react-jsx/node_modules 88 0 -88
packages/babel-helper-call-delegate/node_modules 8 0 -8
packages/babel-helper-compilation-targets/node_modules 4092 56312 52220
packages/babel-helper-create-class-features-plugin/node_modules 8 54040 54032
packages/babel-helper-create-regexp-features-plugin/node_modules 2228 61924 59696
packages/babel-helper-define-map/node_modules 5004 0 -5004
packages/babel-helper-explode-assignable-expression/node_modules 8 0 -8
packages/babel-helper-explode-class/node_modules 8 0 -8
packages/babel-helper-fixtures/node_modules 5092 0 -5092
packages/babel-helper-function-name/node_modules 8 0 -8
packages/babel-helper-get-function-arity/node_modules 8 0 -8
packages/babel-helper-hoist-variables/node_modules 8 0 -8
packages/babel-helper-member-expression-to-functions/node_modules 8 0 -8
packages/babel-helper-module-imports/node_modules 8 56312 56304
packages/babel-helper-module-transforms/node_modules 5004 0 -5004
packages/babel-helper-optimise-call-expression/node_modules 8 0 -8
packages/babel-helper-plugin-test-runner/node_modules 8 0 -8
packages/babel-helper-regex/node_modules 5004 0 -5004
packages/babel-helper-remap-async-to-generator/node_modules 8 0 -8
packages/babel-helper-replace-supers/node_modules 8 0 -8
packages/babel-helper-simple-access/node_modules 8 0 -8
packages/babel-helper-split-export-declaration/node_modules 8 0 -8
packages/babel-helper-transform-fixture-test-runner/node_modules 63644 54040 -9604
packages/babel-helper-wrap-function/node_modules 8 0 -8
packages/babel-helpers/node_modules 8 0 -8
packages/babel-highlight/node_modules 372 0 -372
packages/babel-node/node_modules 12948 57284 44336
packages/babel-parser/node_modules 153368 8 -153360
packages/babel-plugin-external-helpers/node_modules 8 54040 54032
packages/babel-plugin-proposal-async-generator-functions/node_modules 36 98968 98932
packages/babel-plugin-proposal-class-properties/node_modules 8 54040 54032
packages/babel-plugin-proposal-decorators/node_modules 8 56312 56304
packages/babel-plugin-proposal-do-expressions/node_modules 8 56312 56304
packages/babel-plugin-proposal-dynamic-import/node_modules 36 98968 98932
packages/babel-plugin-proposal-export-default-from/node_modules 8 54040 54032
packages/babel-plugin-proposal-export-namespace-from/node_modules 8 102896 102888
packages/babel-plugin-proposal-function-bind/node_modules 8 54040 54032
packages/babel-plugin-proposal-function-sent/node_modules 8 54040 54032
packages/babel-plugin-proposal-json-strings/node_modules 36 98968 98932
packages/babel-plugin-proposal-logical-assignment-operators/node_modules 36 98968 98932
packages/babel-plugin-proposal-nullish-coalescing-operator/node_modules 36 98968 98932
packages/babel-plugin-proposal-numeric-separator/node_modules 8 98968 98960
packages/babel-plugin-proposal-object-rest-spread/node_modules 36 98968 98932
packages/babel-plugin-proposal-optional-catch-binding/node_modules 36 98968 98932
packages/babel-plugin-proposal-optional-chaining/node_modules 36 98968 98932
packages/babel-plugin-proposal-partial-application/node_modules 8 54040 54032
packages/babel-plugin-proposal-pipeline-operator/node_modules 8 56312 56304
packages/babel-plugin-proposal-private-methods/node_modules 8 56312 56304
packages/babel-plugin-proposal-throw-expressions/node_modules 8 54040 54032
packages/babel-plugin-proposal-unicode-property-regex/node_modules 8 54040 54032
packages/babel-plugin-syntax-class-properties/node_modules 8 54040 54032
packages/babel-plugin-syntax-decorators/node_modules 8 54040 54032
packages/babel-plugin-syntax-do-expressions/node_modules 8 54040 54032
packages/babel-plugin-syntax-export-default-from/node_modules 8 54040 54032
packages/babel-plugin-syntax-export-namespace-from/node_modules 8 54040 54032
packages/babel-plugin-syntax-flow/node_modules 8 54040 54032
packages/babel-plugin-syntax-function-bind/node_modules 8 54040 54032
packages/babel-plugin-syntax-function-sent/node_modules 8 54040 54032
packages/babel-plugin-syntax-import-meta/node_modules 8 54040 54032
packages/babel-plugin-syntax-jsx/node_modules 8 54040 54032
packages/babel-plugin-syntax-logical-assignment-operators/node_modules 8 54040 54032
packages/babel-plugin-syntax-numeric-separator/node_modules 8 54040 54032
packages/babel-plugin-syntax-partial-application/node_modules 8 54040 54032
packages/babel-plugin-syntax-pipeline-operator/node_modules 8 54040 54032
packages/babel-plugin-syntax-throw-expressions/node_modules 8 54040 54032
packages/babel-plugin-syntax-top-level-await/node_modules 8 54040 54032
packages/babel-plugin-syntax-typescript/node_modules 8 54040 54032
packages/babel-plugin-transform-arrow-functions/node_modules 8 54040 54032
packages/babel-plugin-transform-async-to-generator/node_modules 8 54040 54032
packages/babel-plugin-transform-block-scoped-functions/node_modules 8 54040 54032
packages/babel-plugin-transform-block-scoping/node_modules 5004 54040 49036
packages/babel-plugin-transform-classes/node_modules 188 54040 53852
packages/babel-plugin-transform-computed-properties/node_modules 8 54040 54032
packages/babel-plugin-transform-destructuring/node_modules 8 54040 54032
packages/babel-plugin-transform-dotall-regex/node_modules 8 54040 54032
packages/babel-plugin-transform-duplicate-keys/node_modules 8 54040 54032
packages/babel-plugin-transform-exponentiation-operator/node_modules 12 54040 54028
packages/babel-plugin-transform-flow-comments/node_modules 8 102896 102888
packages/babel-plugin-transform-flow-strip-types/node_modules 8 102896 102888
packages/babel-plugin-transform-for-of/node_modules 8 54040 54032
packages/babel-plugin-transform-function-name/node_modules 8 54040 54032
packages/babel-plugin-transform-instanceof/node_modules 8 54040 54032
packages/babel-plugin-transform-jscript/node_modules 8 54040 54032
packages/babel-plugin-transform-literals/node_modules 8 54040 54032
packages/babel-plugin-transform-member-expression-literals/node_modules 8 54040 54032
packages/babel-plugin-transform-modules-amd/node_modules 440 54040 53600
packages/babel-plugin-transform-modules-commonjs/node_modules 464 98968 98504
packages/babel-plugin-transform-modules-systemjs/node_modules 464 98968 98504
packages/babel-plugin-transform-modules-umd/node_modules 8 54040 54032
packages/babel-plugin-transform-named-capturing-groups-regex/node_modules 14604 61352 46748
packages/babel-plugin-transform-new-target/node_modules 8 54040 54032
packages/babel-plugin-transform-object-assign/node_modules 8 54040 54032
packages/babel-plugin-transform-object-set-prototype-of-to-assign/node_modules 8 54040 54032
packages/babel-plugin-transform-object-super/node_modules 8 54040 54032
packages/babel-plugin-transform-parameters/node_modules 8 54040 54032
packages/babel-plugin-transform-property-literals/node_modules 8 54040 54032
packages/babel-plugin-transform-property-mutators/node_modules 8 54040 54032
packages/babel-plugin-transform-proto-to-assign/node_modules 5004 54040 49036
packages/babel-plugin-transform-react-constant-elements/node_modules 8 54040 54032
packages/babel-plugin-transform-react-display-name/node_modules 8 54040 54032
packages/babel-plugin-transform-react-inline-elements/node_modules 8 54040 54032
packages/babel-plugin-transform-react-jsx-compat/node_modules 8 54040 54032
packages/babel-plugin-transform-react-jsx-self/node_modules 8 54040 54032
packages/babel-plugin-transform-react-jsx-source/node_modules 8 54040 54032
packages/babel-plugin-transform-react-jsx/node_modules 8 54040 54032
packages/babel-plugin-transform-regenerator/node_modules 216 54040 53824
packages/babel-plugin-transform-reserved-words/node_modules 8 54040 54032
packages/babel-plugin-transform-runtime/node_modules 104 54152 54048
packages/babel-plugin-transform-shorthand-properties/node_modules 8 54040 54032
packages/babel-plugin-transform-spread/node_modules 8 54040 54032
packages/babel-plugin-transform-sticky-regex/node_modules 8 54040 54032
packages/babel-plugin-transform-strict-mode/node_modules 8 54040 54032
packages/babel-plugin-transform-template-literals/node_modules 8 54040 54032
packages/babel-plugin-transform-typeof-symbol/node_modules 8 54040 54032
packages/babel-plugin-transform-typescript/node_modules 8 54040 54032
packages/babel-plugin-transform-unicode-regex/node_modules 8 54040 54032
packages/babel-polyfill/node_modules 7936 0 -7936
packages/babel-preset-env/node_modules 4860 368652 363792
packages/babel-preset-flow/node_modules 8 54040 54032
packages/babel-preset-react/node_modules 8 56312 56304
packages/babel-preset-typescript/node_modules 8 54040 54032
packages/babel-register/node_modules 22172 63524 41352
packages/babel-runtime-corejs2/node_modules 7940 0 -7940
packages/babel-runtime-corejs3/node_modules 7332 0 -7332
packages/babel-runtime/node_modules 56 54040 53984
packages/babel-standalone/node_modules 116 371000 370884
packages/babel-template/node_modules 12 8 -4
packages/babel-traverse/node_modules 5320 8 -5312
packages/babel-types/node_modules 5104 0 -5104

EDIT: I have opened #996, which is the cause of this big size difference.

@larixer larixer marked this pull request as ready for review February 27, 2020 16:04
@larixer larixer requested a review from arcanis February 27, 2020 16:04
@larixer
Copy link
Member Author

larixer commented Feb 27, 2020

@nicolo-ribaudo Currently on this PR I have:

➜  babel git:(yarn-2-compat) ✗ du -s node_modules codemods/*/node_modules eslint/*/node_modules packages/*/node_modules | tr -cd '0-9\n' | xargs | tr ' ' '+' | bc
1191192

Could you give it a shot please?

@nicolo-ribaudo
Copy link
Contributor

Somehow I get way less (644720), but all the tests are passing 👍

Also, this feels faster (I don't know if it's true), because the loading bar appears immediately instead of after a few seconds.

@larixer
Copy link
Member Author

larixer commented Feb 27, 2020

@nicolo-ribaudo Yes, it is much faster, now the hoisting takes 1 second for babel. And I'm still going to improve that in next PRs :)

@larixer
Copy link
Member Author

larixer commented Feb 27, 2020

@nicolo-ribaudo Oh, also the whole thing is much faster thanks to @arcanis PR:
#997
and another one by @crubier will soon be merged:
#998

@nicolo-ribaudo
Copy link
Contributor

OMG I can't believe my eyes 😍

This is with an empty cache:
https://travis-ci.com/babel/babel/jobs/291806125

  • 2m to download from the registry
  • 18.92 SECONDS TO LINK

I guess that the node_modules cache isn't necessary anymore 😄

@arcanis arcanis merged commit 1705a1c into master Feb 27, 2020
@arcanis
Copy link
Member

arcanis commented Feb 27, 2020

🚀

@arcanis arcanis deleted the efficient-dedupe branch February 27, 2020 18:25
@larixer
Copy link
Member Author

larixer commented Feb 29, 2020

@nicolo-ribaudo Sorry, this PR happened to be broken. I have run selfCheck function to check hoisting tree, it generated string, but I forgot to show or throw this string and thought all is well, but in reality it detected errors.

@nicolo-ribaudo
Copy link
Contributor

No worries, I will test the other PR when it doesn't have the "in progress" label 👍

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.

3 participants