简体   繁体   中英

Electron - consistent performance and spinning up a child Node.js process

Before I give some background, I'd like to clarify that I'm not looking for how to simply spawn a new script under the Electron runtime as a renderer process, I'm trying to use a plain Node runtime.

So I'm aware Electron has some different flavor of a JS runtime under its hood similar to NW.js and I'm trying to get consistent performant results for my report.

Unfortunately, this seems to be much more difficult than I had imagined. I'm specifically testing the speed of the mailparser module although that's not necessarily important here.

  1. I first ran it on the Electron app we're working with, which uses Electron Forge. I called the test script through IPC as that's what we intend to use, so it was called within the callback for ipcMain.handle . Here, the performance was really bad and it was taking 30-50 seconds for our test to complete.

  2. I then ran a test script that just opens a blank HTML file in the same Electron Forge app, and runs the test script in the background. This was much better at 8-12 seconds.

Next, I set up a new directory with a test set, a plain Electron installation, and a mailparser installation. I did not electron-rebuild here, but mailparser does rely on node-iconv and so has native bindings.

  1. I ran a test script with Electron just calling the same line of code. This did not use Electron Forge. The performance here was slightly better at 5-9 seconds.

  2. I then ran another test script, this time just with plain old node, and the performance here was excellent at 1-3s.

So I have two questions here:

  1. Why is the performance varying so much in the Electron tests? Although I used IPCMain, I used the new .handle which should be asynchronous and run in the context of Electron's node runtime, so it should have the same performance as running outside the callback. Moreover, the Electron Forge and plain Electron tests also differ by a couple of seconds which made no sense to me as I assumed Electron Forge would just wrap the Electron binary under the hood.

  2. Seeking optimal and consistent results, I'm wondering how I can spin up a child process with the node runtime inside Electron. Doing this normally just starts a new renderer process which is running Electron's (slower) JS runtime. I'd like to avoid leaving Electron Forge but the only solution I can think of is to bundle precompiled binaries with the process running under the Node runtime built for each platform.

For question 1 it's hard to know what the problem is without being able to replicate it in code. You might try posting an issue on the Github site for the Electron team re this. They are more likely to know the answer, but they ask for code as well.

Having said that, it isn't that hard to spin up a child process that is just running node and frees you from Electron/Electron Forge overhead. The easiest is to use node's fork command, but to tell it to use the main node executable rather than electron.exe. You can just hand it a script to run, so you don't need to worry about precompiled binaries.

The code below (and here ) running on the main process will run a script called server.js in the same folder:

    const serverPath = path.join(__dirname, 'server.js');
    const { fork } = require('child_process');
    child = fork(serverPath, [],
        {
            execPath: "node",
            stdio: ['pipe', 'pipe', 'pipe', 'ipc']
        });

If you do that you get a child node.exe process with IPC enabled, rather than an electron.exe process. It can be made to communicate over IPC with the main Electron process. It can also use any npm modules installed from your usual package.json, because the script can be in the same folder as your other scripts. So if it works this is quite a clean solution.

I entertained myself this afternoon by writing some code that does this. I've put this on Github . It uses mailparser to parse a simple mail in the node.exe process in server.js .

This also packages correctly with Electron Forge as far as I can see, in terms of including the correct scripts. It won't package node itself, so that either needs to be installed on the target machine or I think you'll need to distribute node.exe.

By the way it isn't entirely clear whether you've actually tried this approach and it's one of those scenarios where it runs slowly. There is still some overhead, because we're setting up IPC. If it does still run slowly in your use case then I think it's possible to use node's spawn command to create a completely standalone process.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM