电子-一致的性能并加速子Node.js进程

问题描述

在给出背景知识之前,我想澄清一下,我不是在寻找如何在Electron运行时下简单地生成一个新脚本作为渲染器进程,而是尝试使用普通的Node运行时。 / p>

因此,我知道Electron类似于NW.js一样具有JS运行时的不同风格,并且我试图为报告获得一致的性能结果。

不幸的是,这似乎比我想象的要困难得多。我正在专门测试mailparser模块的速度,尽管这在这里不一定很重要。

  1. 我首先在我们正在使用的Electron应用程序上运行它,该应用程序使用Electron Forge。我通过IPC调用了测试脚本,因为这就是我们要使用的脚本,因此在ipcMain.handle的回调中调用了该脚本。在这里性能确实很差,我们的测试需要30到50秒才能完成。

  2. 然后,我运行了一个测试脚本,该脚本仅在同一Electron Forge应用程序中打开一个空白HTML文件,并在后台运行该测试脚本。在8到12秒时,效果要好得多。

接下来,我用测试集,简单的Electron安装和mailparser安装来建立一个新目录。我这里没有electron-rebuild,但是mailparser确实依赖node-iconv,因此也有本地绑定。

  1. 我用Electron运行了一个测试脚本,只是调用了同一行代码。这没有使用Electron Forge。在5到9秒时,这里的性能稍好一些。

  2. 然后我运行了另一个测试脚本,这次只是使用简单的旧节点,并且在1-3s时的性能非常好。

所以我在这里有两个问题:

  1. 为什么在电子测试中性能变化如此之大?尽管我使用了IPCMain,但我使用了新的.handle,它应该是异步的,并且可以在Electron的节点运行时环境中运行,因此它的性能应与在回调外部运行的性能相同。此外,Electron Forge和普通Electron测试也相差了几秒钟,这对我来说是没有意义的,因为我认为Electron Forge只会将电子二进制文件包裹在引擎盖下。

  2. 寻求最佳且一致的结果,我想知道如何使用Electron内部的节点运行时启动子进程。这样做通常只会启动一个新的渲染器进程,该进程正在运行Electron的(较慢的)JS运行时。我想避免离开Electron Forge,但我能想到的唯一解决方案是将预编译的二进制文件与为每个平台构建的Node运行时下运行的进程捆绑在一起。

解决方法

对于问题1,如果无法在代码中复制问题,就很难知道问题出在哪里。您可以尝试为此向电子团队发布issue on the Github site。他们更有可能知道答案,但他们也要求提供代码。

话虽如此,启动一个正在运行节点的子进程并没有多大难度,它可以使您摆脱Electron / Electron Forge的开销。最简单的方法是使用节点的fork命令,但要告诉它使用主节点可执行文件而不是电子文件。您只需将其交给脚本即可运行,因此您无需担心预编译的二进制文件。

在主进程上运行的以下代码(和here)将在同一文件夹中运行名为server.js的脚本:

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

如果执行此操作,则会得到启用了IPC的子node.exe进程,而不是electron.exe进程。可以使其通过IPC与主要的电子过程进行通信。它也可以使用从通常的package.json安装的任何npm模块,因为该脚本可以与其他脚本位于同一文件夹中。因此,如果可行,这是一个非常干净的解决方案。

今天下午,我写了一些代码来招待自己。 I’ve put this on Github。它使用mailparser在server.js中的node.exe进程中解析一个简单的邮件。

就我所见,这也正确包含了Electron Forge,包括正确的脚本。它不会打包节点本身,因此要么需要安装在目标计算机上,要么我认为您需要分发node.exe。

顺便说一下,您是否真的尝试过这种方法还不清楚,这是一种运行缓慢的情况。由于我们正在设置IPC,因此仍有一些开销。如果在您的用例中它仍然运行缓慢,那么我认为可以使用node的spawn命令来创建一个完全独立的进程。