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

Explore lazy code loading #164068

Open
Tyriar opened this issue Oct 19, 2022 · 5 comments
Open

Explore lazy code loading #164068

Tyriar opened this issue Oct 19, 2022 · 5 comments
Assignees
Labels
engineering VS Code - Build / issue tracking / etc. feature-request Request for new features or functionality perf

Comments

@Tyriar
Copy link
Member

Tyriar commented Oct 19, 2022

As VS Code has grown larger and more featureful, so does the main bundle size that increases the time it takes to load/parse/compile the JS linearly. This isn't an issue for anything not in main bundle (shared proc, exthost, ptyhost, built-in extensions, etc.), but code for features like the terminal, tasks and the welcome page are all loaded in even if they are not used yet.

We have had various discussions about this in the past which I don't think are documented anywhere. Here are some of the things discussed and a brain dump of other thoughts on the topic:

  • Moving off AMD (to ESM? Explore AMD to ESM migration #160416) is probably the long term solution to this problem, but it's a large and difficult multi-month project
  • We have not yet measured the actual impact of reducing bundle size, the current assumption is that it will reduce this compile block on startup relative to the percentage of code removed from the bundle
    image
    The section after will reduce some, but I believe that is the code that is run in the top level which is mostly registering contributions which will need to remain in the main bundle.
  • It will be a win if all we're doing is moving non-critical features for the editor to function to LifecyclePhase.Eventually as it will speed up startup
  • Code splitting can be achieved manually by using a technique like in tyriar/code_splitting, but that's a lot of overhead put on the component author.
    • This would ideally be all handled for us by the bundler so we can keep the DX of auto importing and not worrying about what code is included in what bundle as it will inevitably cause problems.
    • Importing code could be prevented by lint rules, but there's still the overhead problem.
  • It makes sense to target editor and workbench contribs are candidates for code splitting, they also typically have some well defined dependencies (eg. tasks depends on terminal, not the other way)
  • xterm.js uses TypeScript projects as a way to make totally separate components of a project even stricter, this is an option we could use if we wanted more strictness around contrib dependencies. Currently this is handled by eslint, to prevent layers going in the wrong direction (common/ cannot depend on browser/) and high level folders (base/ cannot depend on platform/)
@Tyriar Tyriar added perf engineering VS Code - Build / issue tracking / etc. labels Oct 19, 2022
@Tyriar Tyriar added this to the October 2022 milestone Oct 19, 2022
@Tyriar
Copy link
Member Author

Tyriar commented Oct 19, 2022

@jrieken and I discussed this last week but I don't think there's much action we can take until #160416 is explored more? Let me know if you had other things we should look into for October.

@jrieken
Copy link
Member

jrieken commented Oct 21, 2022

Some simple experiments that I am trying to do in October

  • remove all editor-contributions, build, and measure impact on bundle size and load time
  • split the main bundle into separate JS files and see if (sequentially) loading smaller files is better or not

@jrieken
Copy link
Member

jrieken commented Oct 21, 2022

remove all editor-contributions, build, and measure impact on bundle size and load time

I have done the following experiment

  • run yarn run gulp vscode-darwin-arm64-min
  • check the size of out/vs/workbench/workbench.desktop.main.js
  • check the renderer load time: "F1 > Startup Performance > require(workbench.desktop.main.js)"

In step two I have removed all /contrib-imports from editor.all.ts. This builds VS Code without any editor features, no search, no IntelliSense, etc... 1 I then repeated the steps from above.

In step three I have removed many /contrib-imports from workbench.common.main.ts and workbench.desktop.main.ts. This build VS Code without any workbench contributions2. Again, I repeated the measures from above.

size startup (avg of three runs)
full 11.5 MB 309.66 ms
no editor contrib 11.3 MB 305.66 ms
no editor, workbench contrib2 6.4 MB 255 ms

1 some editor contribution still end up in the bundle because they are referenced by other workbench contributions
2 I was NOT ABLE to get a properly working version of VS Code after these changes. Some contributions are needed (files, explorer, ect) and I didn't dig into what exact set that is. So, while a VS Code window came up it was not functional and the measures are unfair.

Finding, learnings, observations

  • It seems that about half of our sources is needed to bring up an empty VS Code window. This confirms past experience from when we would bundle, e.g suggest, search, scm, quick pick ALL depend on the tree/list widget combo, all views depend on the action- and toolbar etc pp.
  • Less code means faster load times. The .2 MB savings from omitting editor-contrib results in little, but consistent savings
  • We need to identify what can be loaded async and how much overhead comes with that.

@jrieken
Copy link
Member

jrieken commented Oct 21, 2022

much action we can take until #160416 is explored more

Not necessarily. AMD is a dead horse but it can do all of this - the only thing that will be simpler with ESM is tree-shaking on a module-level, e.g identify unused module exports and drop them. We do have a custom bundler which we need to blow the dust off that and maybe re-learn how it works.

A tricky thing from the past was knowing how to bundle, e.g some modules are used everywhere and those should be in the initial bundle and not be repeated in subsequent bundles. In the past we realised that most things were in the initial bundle and that contributions were super tiny. That's what might us drop the whole approach. However, by now we have plenty more contributions and this might start to pay off.

@jrieken
Copy link
Member

jrieken commented Nov 25, 2022

We are now down the rabbit hole exploring to migrate from AMD to ESM. While this isn't needed to do bundling and lazy code loading we will benefit from being able to reuse existing bundlers (instead of rolling our own AMD-based solution).

I am snowplowing this for now, if there is urgent need for code splitting: the keyboardLayouts/layout.contribution-modules are a sample of how we are doing it already today

@jrieken jrieken removed this from the November 2022 milestone Nov 25, 2022
@jrieken jrieken added the feature-request Request for new features or functionality label Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
engineering VS Code - Build / issue tracking / etc. feature-request Request for new features or functionality perf
Projects
None yet
Development

No branches or pull requests

2 participants