2
votes

I'm working on electron app with multiple windows. Let say I have the main one and a few child windows.

If I create 20 child windows with google.com open from the main process it spawns around 23 Electron processes(one per each window + GPU process + something else) and consumes around 800 MB in total of memory on my Windows 10 machine. Which is obviously a lot.

const {app, BrowserWindow} = require('electron')

let mainWindow

const webPreferences = {
  sandbox: true
};

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences
  })

  mainWindow.loadFile('index.html')

  for (var t = 0; t < 20; t++) {
    const childWindow = new BrowserWindow({
      webPreferences
    })

    childWindow.loadURL('https://google.com')
  }
}

app.on('ready', createWindow)

Task Manager with 23 Electron processes

I know this is the way Chromium works - each tab is a separate process so if one is broken the whole browser and other tabs are alive. I have no doubt about that but I've noticed one interesting thing. If I use native window.open as described here it mysteriously spawns only 4 processes. Somehow it combines all "window" processes into a single one + GPU + something else which consumes 400 MB in total which is much better result.

const {app, BrowserWindow} = require('electron')

let mainWindow

const webPreferences = {
  sandbox: true // without sandboxing it spawns 23 processes again :(
};

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences
  })

  mainWindow.loadFile('index.html')

  mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => {
    event.preventDefault()
    const win = new BrowserWindow({
      ...options,
      show: false,
      webPreferences
    })
    win.once('ready-to-show', () => win.show())
    if (!options.webContents) {
      win.loadURL(url) // existing webContents will be navigated automatically
    }
    event.newGuest = win
  })
}

app.on('ready', createWindow)

And index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <script>
        for (var t = 0; t < 20; t++) {
            window.open('https://google.com');
        }
    </script>
  </body>
</html>

Task Manager with 4 Electron processes

Is there any way to have only single process for all child windows if I create them from the main process(first snippet)? It would be great if someone could explain why it works that way.

P.S. I'm using electron fiddler with Electron 6.0.2 runtime to run these snippets

1
For the same reason Chrome spawns a new process for each tab; Electron is simply a wrapper around the Chromium rendering engine. What you've run into here is the main reason some people are critical of platforms like Electron - the massive overhead of running a "native" application through a web rendering engine. - MTCoster
Please read the question carefully. I know it is a wrapper. The question is why it spawns a lot of processes if I create a window in the main process but at the same time it spawns only a single process per multiple windows in browser process. - redrick.tmn

1 Answers

0
votes

Update: affinity is being removed, see https://github.com/electron/electron/pull/26874.

The affinity option does the trick. Windows with the same affinity will be gathered together in a single process.

More details on this feature could be found here

https://github.com/electron/electron/pull/11501

and here

https://electronjs.org/docs/api/browser-window#new-browserwindowoptions