99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Electron 性能

2023-02-16 17:15 更新

開發(fā)者經(jīng)常詢問優(yōu)化 Electron 應(yīng)用程序性能的策略。 軟件工程師、用戶和框架開發(fā)者并不總是就“性能”的含義達(dá)成單一定義。 此文檔概述了Electron 維護(hù)者最喜歡的減少內(nèi)存使用、 CPU 負(fù)載以及磁盤資源使用的方式。以確保您的應(yīng)用程序能夠響應(yīng)用戶輸入并盡快完成操作。 此外,我們希望所有的性能策略都能保持您應(yīng)用的高標(biāo)準(zhǔn)安全。

關(guān)于如何使用 JavaScript構(gòu)建高性能網(wǎng)站的技巧和方法通常也適用于Electron 應(yīng)用程序。 在某種程度上,討論如何構(gòu)建高性能 Node.js 應(yīng)用的方法同樣也適用。但是小心理解“性能”一詞的含義對(duì)于 Node.js 后端和客戶端程序并不相同。

文中的列表提供了一些方便,同時(shí)也需要注意,它和我們的 安全性檢查列表 類似,并不詳盡。 即使你參照了下面提到的所有步驟,依然有可能構(gòu)建出來一個(gè)性能低的Electron應(yīng)用。 Electron是一個(gè)強(qiáng)大的開發(fā)平臺(tái),可以讓開發(fā)人員按照自己所想,做更多的或更少的事情。 而這種自由的代價(jià)就是開發(fā)者需要承擔(dān)大部分性能上的責(zé)任。

再三權(quán)衡?

以下列舉了一些直截了當(dāng)、易于實(shí)現(xiàn)的方式。 但是,如果你想構(gòu)建性能最優(yōu)秀的應(yīng)用,僅僅這些是不夠的。 你需要仔細(xì)檢查應(yīng)用中運(yùn)行的所有代碼,認(rèn)真地進(jìn)行分析和衡量。 瓶頸在哪里? 當(dāng)用戶點(diǎn)擊按鈕時(shí),哪些操作的執(zhí)行占用了最多的時(shí)間? 當(dāng)應(yīng)用程序被掛起時(shí),哪些對(duì)象占用了最多的內(nèi)存?

通過多次的嘗試,我們發(fā)現(xiàn),構(gòu)建高性能的Electron應(yīng)用程序,最成功的策略是分析正在運(yùn)行的代碼,查找其中最耗資源的部分,然后對(duì)其進(jìn)行優(yōu)化。 一遍又一遍地重復(fù)這個(gè)“搬磚”的過程,將極大地提高應(yīng)用程序的性能。 在大型應(yīng)用程序(例如Visual Studio Code、Slack)中的實(shí)踐經(jīng)驗(yàn)證明了這是目前最可靠的性能提升策略。

要了解更多關(guān)于如何分析應(yīng)用程序代碼的信息,請(qǐng)熟悉Chrome開發(fā)者工具。 若要高級(jí)分析查看多個(gè)進(jìn)程,請(qǐng)使用 Chrome Tracing 工具。

推薦閱讀?

清單:性能建議?

如果你嘗試這些步驟,你的應(yīng)用可能會(huì)略微簡(jiǎn)潔、快速,而且一般來說會(huì)更少出現(xiàn)資源不足的情況。

  1. 謹(jǐn)慎地加載模塊
  2. 過早的加載和執(zhí)行代碼
  3. 阻塞主進(jìn)程
  4. 阻塞渲染進(jìn)程
  5. 不必要的polyfills
  6. 不必要的或者阻塞的網(wǎng)絡(luò)請(qǐng)求
  7. 打包你的代碼

1. 謹(jǐn)慎地加載模塊?

在向你的應(yīng)用程序添加一個(gè) Node.js 模塊之前,請(qǐng)檢查這個(gè)模塊。 這個(gè)模塊包含了多少依賴? 簡(jiǎn)單的一個(gè)?require()?聲明中包含了什么種類的資源? 你可能發(fā)現(xiàn)NPM包注冊(cè)的最多的或者Github上Star最多的模塊實(shí)際上并不是最簡(jiǎn)單或者最小可用的模塊。

為什么?

這一建議背后的理由最好用一個(gè)真實(shí)的例子來說明。 在Electron最開始的那些日子,可靠的檢查網(wǎng)絡(luò)連接是一個(gè)問題,導(dǎo)致很多應(yīng)用公開的使用了一個(gè)簡(jiǎn)單的isOnline()方法。

該模塊通過嘗試訪問多個(gè)眾所周知的端點(diǎn),檢測(cè)到您的網(wǎng)絡(luò)連接。 至于這些資源的列表,它取決于一個(gè)完全不同的模塊,這個(gè)模塊也包含一個(gè)眾所周知的端口。 這個(gè)依賴本身又依賴一個(gè)包含超過 100 000行端口信息的JSON文件的模塊。 每當(dāng)模塊加載時(shí)(通常用 require('module')),它會(huì)加載所有依賴關(guān)系并最終讀取并解析此 JSON 文件。 解析幾千行的JSON是一個(gè)非常繁重的操作。 在性能差的機(jī)器上,它會(huì)占用整整幾秒的時(shí)間。

在許多服務(wù)器環(huán)境中,啟動(dòng)時(shí)間幾乎無關(guān)緊要。 一個(gè)Node.js 服務(wù)器要求所有端口的信息可能實(shí)際上是“性能更好” 如果服務(wù)器在啟動(dòng)時(shí)將所有需要的信息加載到內(nèi)存,這樣就能更快地為響應(yīng)請(qǐng)求。 此示例中討論的模塊不是一個(gè)“壞”模塊。 然而,Electron 應(yīng)用不應(yīng)該將實(shí)際上不需要的信息加載、解析和存儲(chǔ)在內(nèi)存中。

簡(jiǎn)而言之,一個(gè)主要為運(yùn)行在Linux系統(tǒng)上的Node.js 服務(wù)器編寫的模塊,雖然看起來很好,但是對(duì)你的應(yīng)用性能來說可能是個(gè)壞消息。 在這個(gè)特殊的示例中,正確的解決方案是根本不需要加載模塊, 而是使用了一 個(gè)包含在以后版本的 Chromium 中的連接性檢查。

怎么做?

當(dāng)考慮一個(gè)模塊時(shí),我們建議你做以下檢查:

  1. 包含的依賴項(xiàng)的大小
  2. 需要加載的(?require()?) 資源
  3. 你所加載的資源能夠執(zhí)行你關(guān)心的操作

可以使用命令行上的單個(gè)命令生成用于加載模塊的 CPU 配置文件和堆內(nèi)存配置文件 在下面的示例中,我們看一下受歡迎的模塊 request。

node --cpu-prof --heap-prof -e "require('request')"

執(zhí)行此命令將在您執(zhí)行的目錄下生成一個(gè).cpuprofile和一個(gè).heapprofile 文件。 這兩個(gè)文件都可以使用 Chrome 開發(fā)者工具進(jìn)行分析,分別使用 Performance 和 Memory 標(biāo)簽 進(jìn)行分析。



在這個(gè)例子里,我們看到在作者的機(jī)器上加載request 大概用了半秒鐘,其中 node-fetch明顯占用了極少的內(nèi)存并且加載用時(shí)少于 50ms。

2. 過早的加載和執(zhí)行代碼

如果你有非常繁重的初始化操作,請(qǐng)考慮推遲進(jìn)行。 程序啟動(dòng)立刻查看應(yīng)用執(zhí)行的全部工作。 考慮按照用戶操作的順序?qū)⑺鼈冨e(cuò)開執(zhí)行,而不是立刻執(zhí)行所有的操作。

在傳統(tǒng)的Node.js開發(fā)中,我們習(xí)慣將所有的require()語句放在代碼頂部。 如果你目前正在使用相同的策略and并且使用你不需要立即加載的大型模塊編寫你的 Electron 應(yīng)用程序,使用相同的策略并推遲到更適當(dāng)?shù)臅r(shí)機(jī)加載。

為什么?

加載模塊是令人吃驚的繁重的操作,尤其是在Windows上。 當(dāng)你的應(yīng)用開始,不應(yīng)該讓用戶等待當(dāng)時(shí)不需要的操作。

這似乎是顯而易見的, 但許多應(yīng)用程序在程序啟動(dòng)后可能會(huì)馬上完成大量的 工作 - 如檢查更新,正在下載稍后流程中使用的內(nèi)容,或執(zhí)行大型的磁盤I/O 操作。

讓我們把Visual Studio 代碼作為一個(gè)例子。 當(dāng)你打開一個(gè)文件,它會(huì)立刻展示沒有高亮任何代碼的內(nèi)容,優(yōu)先實(shí)現(xiàn)和文本交互的功能。 一旦它完成了這項(xiàng)工作,它將繼續(xù)讓代碼高亮。

怎么做?

讓我們考慮一個(gè)示例,并假定您的應(yīng)用程序正在以架空的.foo形式解析文件 。 為了做到這一點(diǎn),它依賴同樣架空的foo-parserver 模塊。 在傳統(tǒng)的 Node.js 開發(fā)中,你可以寫代碼熱加載依賴:

const fs = require('fs')
const fooParser = require('foo-parser')

class Parser {
  constructor () {
    this.files = fs.readdirSync('.')
  }

  getParsedFiles () {
    return fooParser.parse(this.files)
  }
}

const parser = new Parser()

module.exports = { parser }

在上面的例子中,我們做了很多工作,一旦文件加載,我們就會(huì)立即執(zhí)行。 我們需要立即獲取解析的文件嗎? 或許我們可以晚一點(diǎn)再做這件事,當(dāng)getParsedFiles() 真正的執(zhí)行到的時(shí)候?

// "fs" is likely already being loaded, so the `require()` call is cheap
const fs = require('fs')

class Parser {
  async getFiles () {
    // Touch the disk as soon as `getFiles` is called, not sooner.
    // Also, ensure that we're not blocking other operations by using
    // the asynchronous version.
    this.files = this.files || await fs.readdir('.')

    return this.files
  }

  async getParsedFiles () {
    // Our fictitious foo-parser is a big and expensive module to load, so
    // defer that work until we actually need to parse files.
    // Since `require()` comes with a module cache, the `require()` call
    // will only be expensive once - subsequent calls of `getParsedFiles()`
    // will be faster.
    const fooParser = require('foo-parser')
    const files = await this.getFiles()

    return fooParser.parse(files)
  }
}

// This operation is now a lot cheaper than in our previous example
const parser = new Parser()

module.exports = { parser }

簡(jiǎn)而言之,只有當(dāng)需要的時(shí)候才分配資源,而不是在你的應(yīng)用啟動(dòng)時(shí)分配所有。

3. 阻塞主進(jìn)程

Electron的主要進(jìn)程(有時(shí)稱為“瀏覽器進(jìn)程”) 非常特殊:它是與你應(yīng)用的所有其他進(jìn)程的父進(jìn)程,也是和操作系統(tǒng)交互的關(guān)鍵進(jìn)程。它處理窗口、交互以及應(yīng)用程序內(nèi)各個(gè)組件之間的通信。它還包含 UI 線程。

在任何情況下你都不應(yīng)阻塞此進(jìn)程或者運(yùn)行時(shí)間長的用戶界面線程。 阻塞UI線程意味著您的整個(gè)應(yīng)用程序?qū)鼋Y(jié)直到主進(jìn)程準(zhǔn)備好繼續(xù)處理。

為什么??

主進(jìn)程及其 UI 線程本質(zhì)上是應(yīng)用程序內(nèi)部主要操作的控制塔。當(dāng)操作系統(tǒng)告訴您的應(yīng)用程序有關(guān)鼠標(biāo)單擊的信息時(shí),它會(huì)在到達(dá)您的窗口之前完成主進(jìn)程。如果您的窗口呈現(xiàn)黃色平滑動(dòng)畫, 它需要和 GPU 進(jìn)程進(jìn)行通信——再次穿越主進(jìn)程。

Electron 和 Chromium 謹(jǐn)慎地將大型的磁盤I/O 和 CPU綁定的操作放入新線程,以避免阻塞UI 線程。 你也應(yīng)該這樣做。

怎么做??

Electron強(qiáng)大的多進(jìn)程架構(gòu)隨時(shí)準(zhǔn)備幫助你完成你的長期任務(wù),但其中也包含少量性能陷阱。

  1. 對(duì)于需要長期占用 CPU 的繁重任務(wù),利用worker threads,請(qǐng)考慮將它們移動(dòng)到 BrowserWindow,或(作為最后手段)生成一個(gè)專用進(jìn)程。

  2. 盡可能避免使用同步 IPC 和 @electron/remote 模塊。 雖然有合法的使用案例,但很容易不知情地阻塞 UI 線程。

  3. 避免在主進(jìn)程中使用阻塞 I/O 操作。 簡(jiǎn)而言之,每當(dāng)Node.js的核心模塊 (如fschild_process) 提供一個(gè)同步版本或 異步版本,你更應(yīng)該使用異步和非阻塞式的變量。

4. 阻塞渲染進(jìn)程

自從 Electron 使用了當(dāng)前版本的 Chrome,你可以使用Web 平臺(tái)提供的最新和最優(yōu)秀的功能來推遲或卸載繁重的操作,以使你的應(yīng)用保持流暢和迅速的反應(yīng)。

為什么??

你的應(yīng)用可能有很多JavaScript在渲染過程中運(yùn)行。 有個(gè)技巧是盡快執(zhí)行操作,而不占用保持滾動(dòng)平滑、響應(yīng)用戶輸入或60幀/秒動(dòng)畫所需的資源。

如果有用戶抱怨你的應(yīng)用“口吃”的時(shí)候在渲染的代碼中編排操作流就顯得尤其重要。

怎么做?

一般來說,所有用于構(gòu)建現(xiàn)代瀏覽器的性能網(wǎng)絡(luò)應(yīng)用程序的建議,對(duì)于Electron 的渲染器也同樣適用。 現(xiàn)在處理你的應(yīng)用的主要兩個(gè)方法是對(duì)于小的操作使用requestIdleCallback() 而長時(shí)間運(yùn)行的操作使用 Web Workers。

requestIdleCallback()允許開發(fā)者將函數(shù)排隊(duì)為在進(jìn)程進(jìn)入空閑期后立刻執(zhí)行。 它使你能夠在不影響用戶體驗(yàn)的情況下執(zhí)行低優(yōu)先級(jí)或后臺(tái)執(zhí)行的工作。 想要了解如何使用它的更多信息,請(qǐng)查看MDN上的文檔。

Web Workers是在單獨(dú)線程上運(yùn)行代碼的一個(gè)好方式。 有一些注意事項(xiàng)需要考慮 - 請(qǐng)查閱 Electron 的 多線程文檔 和 MDN 的 Web Workers文檔。 對(duì)于長時(shí)間并且大量使用CPU的操作來說它們是一個(gè)理想的解析器。

5. 不必要的polyfills?

Electron的一大好處是,你準(zhǔn)確地知道哪個(gè)引擎將解析你的 JavaScript, HTML和CSS。 如果你重新設(shè)計(jì)的代碼是為整個(gè)網(wǎng)頁編寫的,請(qǐng)確保不會(huì)polyfill包含在Electron 中的特性。

為什么??

現(xiàn)在互聯(lián)網(wǎng)構(gòu)建網(wǎng)頁應(yīng)用程序時(shí),最老的環(huán)境決定了你能夠和不能使用的功能。 盡管Electron支持性能良好的 CSS 選擇器和動(dòng)畫,但是較早的瀏覽器可能不支持。 在你可以使用WebGL的場(chǎng)合,你的開發(fā)者可能選擇了一個(gè)資源更加匱乏的解決方案來支持舊機(jī)器。

當(dāng)它遇到JavaScript時(shí), 你可能已經(jīng)包含了工具包庫,如DOM選擇器 jQuery 或是 如regenerator-runtime支持async/await 的polyfills。

基于 JavaScript 的polyfill速度比Electron 中的原生特征要快一些。 不要通過發(fā)布你自己的網(wǎng)絡(luò)平臺(tái)標(biāo)準(zhǔn)來減慢你的 Electron 應(yīng)用速度。

怎么做?

假定當(dāng)前版本的 Electron不需要使用polyfills。 如果你有所疑慮,檢查 caniuse.com 以確認(rèn) 是否 在你的Electron版本中使用的Chromium版本 已經(jīng)支持了你需要的特性.

此外,仔細(xì)檢查您使用的三方庫。 它們是否真的必要? 例如,jQuery非常成功,它的許多功能現(xiàn)在都是 標(biāo)準(zhǔn)JavaScript功能設(shè)置的 的一部分

如果您正在使用 TypeScript 這樣的編譯器,檢查它的配置并確保你的目標(biāo)是Electron 支持的最新 ECMAScript 版本。

6. 不必要的或者阻塞的網(wǎng)絡(luò)請(qǐng)求?

避免從互聯(lián)網(wǎng)中獲取幾乎不變化的資源,如果它可以輕松地與你的應(yīng)用程序捆綁起來。

為什么?

許多開始使用基于Web的應(yīng)用程序的Electron用戶后來都使用了桌面應(yīng)用。 作為網(wǎng)頁開發(fā)者,我們習(xí)慣了從各種內(nèi)容交付網(wǎng)站加載資源。既然您正在發(fā)布一個(gè)合適的桌面應(yīng)用程序,請(qǐng)盡可能嘗試“切斷電源”并避免讓您的用戶等待永遠(yuǎn)不會(huì)更改并且可以輕松包含在您的應(yīng)用程序中的資源。

一個(gè)典型的例子是谷歌字體。 許多開發(fā)者使用谷歌令人印象深刻的免費(fèi)字體集,這些字體通過內(nèi)容交付網(wǎng)絡(luò)獲取。 方法顯而易見:包括幾行CSS 和谷歌將處理其余部分。

構(gòu)建Electron應(yīng)用程序時(shí),如果你下載字體并將其包含在應(yīng)用包中,你的用戶將會(huì)得到更好的服務(wù)。

怎么做?

在理想情況下,你的應(yīng)用程序不需要網(wǎng)絡(luò)就可以運(yùn)行。 要達(dá)到這個(gè)目標(biāo),你必須了解你的應(yīng)用正在下載哪些資源以及這些資源的大小。

要做到這一點(diǎn),請(qǐng)打開開發(fā)者工具。 導(dǎo)航到 Network 選項(xiàng)卡,然后檢查 Disable cache 選項(xiàng)。 然后重新加載你的頁面。 除非你的應(yīng)用禁止重新加載, 你通常可以在使用開發(fā)者工具時(shí)點(diǎn)擊Cmd + R 或Ctrl + R觸發(fā)重新加載。

開發(fā)者工具將仔細(xì)記錄所有網(wǎng)絡(luò)請(qǐng)求。 第一步,評(píng)估正在下載的所有資源,首先側(cè)重于較大的文件。 其中是否有任何圖像、字體或媒體文件不會(huì)改變并且可以包含在你的包中? 如果可以,把它們打包。

下一步,啟用 Network Throttling。 查找當(dāng)前讀取Online的下拉列表,并選擇較慢的速度,例如Fast 3G。 重新加載你的頁面并查看你的應(yīng)用程序是否有等待任何不必要的資源。 在大多數(shù)情況下,盡管實(shí)際上不需要相關(guān)的資源,應(yīng)用還是會(huì)等待網(wǎng)絡(luò)請(qǐng)求完成。

作為一個(gè)提示, 從互聯(lián)網(wǎng)上加載你可能想要更改的而不發(fā)送應(yīng)用程序更新是一個(gè)強(qiáng)有力的策略。 為了進(jìn)一步控制如何加載資源,請(qǐng)考慮使用Service Worker。

7. 打包你的代碼

正如中已經(jīng)指出的那樣,"加載和運(yùn)行代碼太早", 調(diào)用 require() 是一項(xiàng)繁重的操作。 如果你能夠這樣做,將你的應(yīng)用程序的代碼打包到單個(gè)文件中。

為什么?

現(xiàn)代JavaScript開發(fā)通常涉及許多文件和模塊。 對(duì)于使用Electron開發(fā)的人來說這是非常好的事情,我們強(qiáng)烈建議你將你的代碼打包到單個(gè)文件中以確保調(diào)用require() 時(shí)只在你的應(yīng)用加載花費(fèi)一次開銷。

怎么做??

有許多JavaScript打包的方法可供使用,我們知道我們最好不要通過推薦一種工具來激怒社區(qū)。 然而,我們的確建議您使用一個(gè)能夠處理Electron獨(dú)特的環(huán)境的打包程序,它需要處理Node.js 和瀏覽器兩種環(huán)境。

在撰寫這篇文章時(shí),受歡迎的選擇包括WebpackParcelrollup.js。

8. 不需要默認(rèn)菜單時(shí)調(diào)用 Menu.setApplicationMenu(null)

Electron 將在啟動(dòng)時(shí)使用一些標(biāo)準(zhǔn)條目設(shè)置默認(rèn)菜單。但是您的應(yīng)用程序可能出于某些原因想要更改它,這將有利于啟動(dòng)性能。

為什么??

如果您構(gòu)建自己的菜單或使用沒有原生菜單的無框窗口,您應(yīng)該盡早告訴 Electron 不要設(shè)置默認(rèn)菜單。

怎么做?

在 ?app.on("ready")? 之前調(diào)用 ?Menu.setApplicationMenu(null)?。這將阻止 Electron 設(shè)置默認(rèn)菜單。有關(guān)相關(guān)討論,另請(qǐng)參閱 https://github.com/electron/electron/issues/35512


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)