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

Atom Startup Time #13253

as-cii opened this issue Nov 17, 2016 · 2 comments

Atom Startup Time #13253

as-cii opened this issue Nov 17, 2016 · 2 comments
FY2019Q5 atom perf performance startup-time triaged


Copy link

@as-cii as-cii commented Nov 17, 2016

The following is a summary of a CPU profile taken during startup. The aim of this issue is to explicitly state what the bottlenecks are and, where possible, suggest ideas on how to solve them. Profiles were taken after disabling all the 3rd party packages.

  • Bootstrap Node.
    Cost: ~ 100ms.
    Savings: N/A.
    Difficulty: Medium/Hard.

    screen shot 2016-11-17 at 13 53 58

    This section involves setting up Node and is standard for all the projects. The bottom line is that it would require a change in Electron, hence why I chose Medium/Hard as the difficulty. It might be worth exploring solutions with the Electron team as well as talking to the Node team, understanding if there are plans to improve this in the future.

    An interesting observation is that most of it is spent in requiring modules, so maybe Electron/Node could employ some of the techniques we plan to use for userland requires (see below).

  • Requiring modules.
    Cost: ~ 350-400 ms.
    Savings: 90-100%.
    Difficulty: Medium/Hard.

    This sections concerns the time spent in searching, compiling and executing JavaScript files. I haven't provided a screenshot of the CPU profile because this cost is spread across many function calls.

    So long as modules don't access Node core modules or DOM APIs at require-time, we should be able to use v8 snapshots to do most of the work during script/build. This means we would need to restructure some packages to stop using those APIs, but it should be doable. Last week we have been working on proving the feasibility of this approach and it seems like we could apply it to Atom.

  • Constructing AtomEnvironment.
    Cost: ~ 100-110ms.
    Savings: 75-80%.
    Difficulty: Medium.

    screen shot 2016-11-17 at 14 08 52

    The above chart breaks down into several sub-tasks. Some of them can be executed upfront in the snapshotting phase:

    • Creating objects like Workspace, TextEditorRegistry, etc.(~ 10ms).
    • Config.setSchema (~ 7ms).
    • ThemeManager.loadBaseStylesheets (~ 19ms).
    • KeymapManager.loadBundledKeymaps (~ 11ms)

    Others need to happen at runtime, although we can make them asynchronous and avoid blocking the main thread:

    • ApplicationDelegate.disableZoom (~ 9ms).
    • AtomEnvironment.registerDefaultCommands (~ 7ms).
    • AtomEnvironment.installWindowEventHandler (~ 7ms).
    • HistoryManager.loadState (~ 25ms).
    • Config.loadUserConfig (~ 5ms).
  • Loading Packages.
    Cost: ~ 50-60ms.
    Savings: 90-100%.
    Difficulty: Medium.

    screen shot 2016-11-17 at 13 15 15

    Loading packages involves reading their style sheets and their configuration schemas. The image above is the typical chart of a single Package.load call. At least for bundled packages, we have all the information at compile-time and we should be able to bake it into the snapshot.

  • Environment Deserialization.
    Cost: ~ 50-60ms.
    Savings: 70%.
    Difficulty: N/A.

    screen shot 2016-11-17 at 13 16 21

    Deserializing the environment is something that needs to happen at runtime but, as the chart above shows, the dominator in that stack trace is GitRepository. In particular, it might be worth revisiting openSubmodules and refreshStatus: the former can probably be deferred at a later moment in time, while the latter is already asynchronous and is probably slow because of the overhead of creating a Task.

  • Activating Packages.
    Cost: ~ 300ms.
    Savings: N/A
    Difficulty: Medium/Hard.

    screen shot 2016-11-17 at 14 39 47

    Estimating savings for this section is somewhat tricky, as a considerable amount of time is spent in requiring modules (which has been accounted for in a previous section). However, we think we could further reduce the cost of it by splitting core packages activation into two phases (snapshot and runtime), offloading as much work as possible to the snapshot one.

  • Refreshing less cache and reloading base style sheets.
    Cost: ~ 20ms.
    Savings: 90-100%
    Difficulty: N/A.

    screen shot 2016-11-17 at 14 55 48

    The first thing that is suspicious is that this stack trace feels redundant, as we do a similar thing when instantiating AtomEnvironment. Anyways, this is all information we have at compile time, so the only cost we should pay at runtime is to add the proper CSS to the <head> element.

  • First Layout
    Cost: ~ 250ms.
    Savings: N/A
    Difficulty: Hard.

    screen shot 2016-11-17 at 14 59 03

    This is the first layout that Atom performs after loading and it takes a pretty huge amount of time. Unfortunately, we cannot inspect what is happening under the hood that causes this layout to be slow. We suspect it might be due to our use of flexbox, but at the same time we feel like it might be worth capturing a native profile of Electron and inspecting the actual native calls that are being executed.

  • Main Process.
    Cost: ~ 600ms.
    Savings: N/A
    Difficulty: N/A.

    Profiling the main process is somewhat trickier than profiling the renderer process, as we don't have direct access to the dev tools. However, I have estimated that we spend ~ 600ms to get from the first line of code in the main process to the first line of code in the renderer process. This section probably deserves an entire issue, as we are aware that the main process needs a overhaul. However it's worth noting that it significantly contributes to startup time, although it's unclear how much of it is Atom's fault and how much of it is due to Electron.

/cc: @atom/maintainers

Copy link

@zshift zshift commented Apr 20, 2017

@as-cii what tool did you use to make these flame graphs?

Copy link

@whmountains whmountains commented Apr 22, 2017

@as-cii Um, the Chromium developer tools. Just hit Opt-Cmd-I inside Atom and they'll show up.

@daviwil daviwil added the startup-time label Feb 5, 2019
@rafeca rafeca added the FY2019Q5 atom perf label Mar 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
FY2019Q5 atom perf performance startup-time triaged
None yet

No branches or pull requests

7 participants