Electron 應(yīng)用的啟動(dòng)速度優(yōu)化可以分為以下幾個(gè)步驟:
性能分析蒸走,確定瓶頸
提升代碼加載速度
在正確的時(shí)間執(zhí)行任務(wù)
持續(xù)優(yōu)化代碼
1. 性能分析列牺,確定瓶頸
1.1 性能監(jiān)測(cè)和分析
Electron 可分為主進(jìn)程和渲染進(jìn)程鄙漏,其性能分析有所不同招驴。
1.1.1 渲染進(jìn)程
渲染進(jìn)程和一般的 web 工程一樣草冈,可以直接用 devtools 的性能面板進(jìn)行分析她奥。性能面板的使用已有不少教程,此處不再贅述怎棱。
-
渲染進(jìn)程的 js 性能哩俭,也可以用 devtools 的
Javascript Profiler
面板進(jìn)行分析。 選擇More tools
-Javascript Profiler
拳恋,即可打開面板凡资,然后點(diǎn)擊Start
開始監(jiān)測(cè),點(diǎn)擊Stop
停止監(jiān)測(cè)谬运。
image.png
得到的結(jié)果以列表形式展示隙赁,耗時(shí)越長(zhǎng)的位置越靠上垦藏,可以方便地查看耗時(shí)最多的函數(shù)。另外伞访,一條數(shù)據(jù)可以看到每個(gè)函數(shù)的自身時(shí)間和總時(shí)間掂骏,點(diǎn)擊后面的鏈接可以跳轉(zhuǎn)到函數(shù)對(duì)應(yīng)的文件位置。
監(jiān)測(cè)結(jié)果也可以按火焰圖的形式展示咐扭,鼠標(biāo)懸浮時(shí)芭挽,可以展示自身時(shí)間和全部時(shí)間,點(diǎn)擊可以跳轉(zhuǎn)到函數(shù)對(duì)應(yīng)的文件位置蝗肪。
1.1.2 主進(jìn)程和其他子進(jìn)程
主進(jìn)程袜爪,可以用 v8-inspect-profiler 進(jìn)行性能監(jiān)測(cè)。生成的
.cpuprofile
文件薛闪,可以用 devtools 上的Javascript Profiler
進(jìn)行分析辛馆。如果用 fork 等方法啟動(dòng)了子進(jìn)程,也可以用相同的方法監(jiān)測(cè)豁延,只需要設(shè)置不同的監(jiān)測(cè)端口昙篙。v8-inspect-profiler
在 electron 中的使用示例 設(shè)置啟動(dòng)命令,添加參數(shù)--inspect=${port}
诱咏,設(shè)置主進(jìn)程的 v8 調(diào)試端口苔可。 監(jiān)測(cè)主進(jìn)程和通過 fork 啟動(dòng)的子進(jìn)程,分別設(shè)置端口號(hào)為 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 單個(gè)依賴模塊
- 我們需要謹(jǐn)慎加載 npm 模塊,因?yàn)橐粋€(gè)模塊可能包含了超出實(shí)際所需的功能苟鸯,而 require 模塊消耗的時(shí)間相當(dāng)可觀同蜻。可以運(yùn)行以下命令早处,監(jiān)測(cè)單個(gè)模塊的加載時(shí)間: 執(zhí)行命令會(huì)生成 .cpuprofile 和 .heapprofile 文件湾蔓,可以通過 devtools 的性能面板、內(nèi)存面板進(jìn)行分析砌梆。
node --cpu-prof --heap-prof -e "require('request')"
1.2. 性能鉤子計(jì)時(shí)
除了使用上述性能監(jiān)測(cè)工具默责,還可以測(cè)量啟動(dòng)過程中主要步驟的耗時(shí),大致確認(rèn)性能瓶頸在哪里么库。
- 可以使用 node 的
perf_hook
進(jìn)行打點(diǎn)計(jì)時(shí)傻丝,生成性能時(shí)間軸。示例如下: 打印結(jié)果如下: