Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with slow Electron startup

Context

I have spent some hours playing with Electron and I have observed that it consistently takes more than 2.5 seconds to draw a trivial html file to the screen. The timeline is roughly as follows:

  • 60 ms: app ready event is triggered; we create a window using new BrowserWindow()
  • 170 ms: a blank window appears on the screen
  • 2800 ms: the window shows the specified HTML

I have set up a repository with my code, which is derived from Electron's quick start docs.

Regarding my machine, I am running Windows 10 on a ThinkPad T460 from 2016 with a SSD and enough memory.

Questions

Shipping an application that shows a blank window for so long upon startup is a no-go for me. I assume most people developing Electron apps think similarly. Hence my first question: am I doing something wrong? Or is this the expected loading time for a trivial Electron app?

Assuming this is normal behavior, what is the common way to deal with this problem? Some ideas come to mind:

  1. Asking Electron to show a splash screen: unless there is specific built-in functionality for this, it seems like a no-go, since the splash screen itself would be shown only after 2.5 seconds.
  2. Hide the app's window until it is rendered (using the ready-to-show event), so no blank window is shown. This isn't ideal, since it means that the user doesn't get any feedback whatsoever that the application is actually loading.
  3. Create a wrapper application (using native code) that displays a splash screen, launches electron and hides itself once the electron window is shown. Kind of defeats the purpose of using Electron in the first place, because you end up writing native code and adding accidental complexity.
  4. Setting the background color of the window to something resembling your app, as suggested by the docs. This just doesn't look very well.

Given this must be a common problem, I hope standard solutions have been found by the community. I'd be glad if someone can point me in the right direction.

like image 437
aochagavia Avatar asked Jun 07 '21 15:06

aochagavia


People also ask

Why is the Electron app so slow?

It is just the renderer, and just like a web app in a regular browser, it uses HTML, CSS and JavaScript to build an interface and provide functionality. Those are a lot of extra layers. And because of this additional abstraction, it can be slower than a finely tuned native app.

Why does Electron use so much memory?

Electron will use a ton of memory because it's running a full browser inside a browser/desktop, Chromium, along with running v8 and all of it's own code. Along with that Chromium is already known for high memory usage. So it's relatively normal to see high memory.

Can Electron app fast?

Electron's number one strength is its turnaround speed. No other application development framework can go from 0 to fully functioning app as quickly as Electron can. Recently we were able to turnaround an app for a client in 2 weeks, because it was built on top of an existing React library.


2 Answers

Short answer

Windows Defender is causing the slowdown, so this is not an Electron problem.

Long answer

It turns out that Windows Defender real-time protection causes startup to last much longer than needed. After turning real-time protection off, we achieved acceptable performance:

  • 55 ms: app ready
  • 150 ms: blank window shown
  • 500 ms: HTML loaded and shown

This means that option 1 of my proposed solutions (showing a splash screen) should work quite well for slow-loading apps.

The only thing left is to figure out how to solve the Windows Defender problem. For that purpose, I have asked a new question.

like image 144
aochagavia Avatar answered Oct 18 '22 17:10

aochagavia


What if you hid your window until it's ready to show, then show your window, and while your window's hidden show a loading spinner.

First only show your main window until after it's ready:

var mainWindow = new BrowserWindow({
    show: false
});
mainWindow.webContents.once('did-finish-load', function ()
{
    mainWindow.show();
    loadingWindow.close();
});

Meanwhile show a loading spinner:

var loadingWindow = new BrowserWindow({
    width:          200,
    height:         200,
    transparent:    (process.platform != 'linux'), // Transparency doesn't work on Linux.
    resizable:      false,
    frame:          false,
    alwaysOnTop:    true,
    hasShadow:      false,
    title:          "Loading..."
});
loadingWindow.loadURL('file://' + __dirname + '/loadingAnimation.gif');
like image 41
Joshua Avatar answered Oct 18 '22 19:10

Joshua