Electron 应用的启动速度优化可以分为以下几个步骤:
性能分析,确定瓶颈
提升代码加载速度
在正确的时间执行任务
持续优化代码
1. 性能分析,确定瓶颈
1.1 性能监测和分析
Electron 可分为主进程和渲染进程,其性能分析有所不同。
1.1.1 渲染进程
渲染进程和一般的 web 工程一样,可以直接用 devtools 的性能面板进行分析。性能面板的使用已有不少教程,此处不再赘述。
-
渲染进程的 js 性能,也可以用 devtools 的
Javascript Profiler
面板进行分析。 选择More tools
-Javascript Profiler
,即可打开面板,然后点击Start
开始监测,点击Stop
停止监测。
得到的结果以列表形式展示,耗时越长的位置越靠上,可以方便地查看耗时最多的函数。另外,一条数据可以看到每个函数的自身时间和总时间,点击后面的链接可以跳转到函数对应的文件位置。
监测结果也可以按火焰图的形式展示,鼠标悬浮时,可以展示自身时间和全部时间,点击可以跳转到函数对应的文件位置。
1.1.2 主进程和其他子进程
主进程,可以用 v8-inspect-profiler 进行性能监测。生成的
.cpuprofile
文件,可以用 devtools 上的Javascript Profiler
进行分析。如果用 fork 等方法启动了子进程,也可以用相同的方法监测,只需要设置不同的监测端口。v8-inspect-profiler
在 electron 中的使用示例 设置启动命令,添加参数--inspect=${port}
,设置主进程的 v8 调试端口。 监测主进程和通过 fork 启动的子进程,分别设置端口号为 5222 和 5223,输出到prof-test.main.cpuprofile
和prof-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
进行打点计时,生成性能时间轴。示例如下: 打印结果如下: