Electron开发: 提升 Electron 应用的启动速度

Electron 应用的启动速度优化可以分为以下几个步骤:

  • 性能分析,确定瓶颈

  • 提升代码加载速度

  • 在正确的时间执行任务

  • 持续优化代码

1. 性能分析,确定瓶颈

1.1 性能监测和分析

Electron 可分为主进程和渲染进程,其性能分析有所不同。

1.1.1 渲染进程

  • 渲染进程和一般的 web 工程一样,可以直接用 devtools 的性能面板进行分析。性能面板的使用已有不少教程,此处不再赘述。

  • 渲染进程的 js 性能,也可以用 devtools 的 Javascript Profiler 面板进行分析。 选择 More tools - Javascript Profiler,即可打开面板,然后点击 Start 开始监测,点击 Stop 停止监测。

    image.png

得到的结果以列表形式展示,耗时越长的位置越靠上,可以方便地查看耗时最多的函数。另外,一条数据可以看到每个函数的自身时间和总时间,点击后面的链接可以跳转到函数对应的文件位置。


image.png

监测结果也可以按火焰图的形式展示,鼠标悬浮时,可以展示自身时间和全部时间,点击可以跳转到函数对应的文件位置。


image.png

1.1.2 主进程和其他子进程

  • 主进程,可以用 v8-inspect-profiler 进行性能监测。生成的 .cpuprofile 文件,可以用 devtools 上的 Javascript Profiler 进行分析。如果用 fork 等方法启动了子进程,也可以用相同的方法监测,只需要设置不同的监测端口。

  • v8-inspect-profiler 在 electron 中的使用示例 设置启动命令,添加参数 --inspect=${port},设置主进程的 v8 调试端口。 监测主进程和通过 fork 启动的子进程,分别设置端口号为 5222 和 5223,输出到 prof-test.main.cpuprofileprof-test.fork.cpuprofile 文件中。

{
    "name": "test",
    "version": "1.0.0",
    "main": "main.js",
    "devDependencies": {
        "electron": "9.2.1"
    },
    "scripts": {
        "start": "electron . --inspect=5222"
    },
    "dependencies": {
        "v8-inspect-profiler": "^0.0.20"
    }
}
const { app, BrowserWindow } = require('electron');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { fork } = require('child_process');

app.on('ready', async() => {

    const mainProfiler = await startProfiler('main', 5222);

    const mainWindow = new BrowserWindow({width: 800,height: 800});
    const mainWindow.loadURL(`file://${__dirname}/index.html`);

    startChildProcess();

    ...

    const mainProfiler.stop();
});

...

async function startProfiler(name, port) {
    const profiler = require('v8-inspect-profiler');

    const profiling = await profiler.startProfiling({port});

    return {
        async stop() {
            const profile = await profiling.stop();
            const prefix = path.join(os.homedir(), 'prof-test');

            await profiler.writeProfile(profile, `${prefix}.${name}.cpuprofile`);
        }
    }
}

async function startChildProcess() {
    const forkProcess = fork(
        path.join(__dirname, `child-process.js`),

        { execArgv: ['--inspect=5223'] }
    );

    const forkProfiler = await startProfiler('fork', 5223);
    setTimeout(async () => {

        await forkProfiler.stop();
    }, 60000);
}

1.1.3 单个依赖模块

  • 我们需要谨慎加载 npm 模块,因为一个模块可能包含了超出实际所需的功能,而 require 模块消耗的时间相当可观。可以运行以下命令,监测单个模块的加载时间: 执行命令会生成 .cpuprofile 和 .heapprofile 文件,可以通过 devtools 的性能面板、内存面板进行分析。
node --cpu-prof --heap-prof -e "require('request')"

1.2. 性能钩子计时

除了使用上述性能监测工具,还可以测量启动过程中主要步骤的耗时,大致确认性能瓶颈在哪里。

  • 可以使用 node 的 perf_hook 进行打点计时,生成性能时间轴。示例如下: 打印结果如下:

你可能感兴趣的:(Electron开发: 提升 Electron 应用的启动速度)