📜  在 ElectronJS 中创建 V8 堆快照

📅  最后修改于: 2021-11-08 06:23:41             🧑  作者: Mango

ElectronJS是一个开源框架,用于使用能够在 WindowsmacOSLinux操作系统上运行的 HTML、CSS 和 JavaScript 等 Web 技术构建跨平台原生桌面应用程序。它将 Chromium 引擎和NodeJS 组合成一个单一的运行时。

NodeJS是一个 JavaScript 运行时,它使用 Chrome 的 V8 引擎。 NodeJS 具有许多优点,使其成为包括 RESTful API 在内的后端解决方案的首选。然而,NodeJS 确实有一些与之相关的缺点。 NodeJS 的主要缺点之一是由于繁重的计算任务导致的性能瓶颈。这是因为 NodeJS 是单线程的。这会导致处理缓慢,这就是为什么不建议使用 NodeJS 进行大量计算的原因。在 Electron 应用中,我们需要确保 NodeJS 没有内存泄漏,这会进一步降低性能。因此,Electron 为我们提供了一种使用BrowserWindow对象的实例方法和 webContents属性获取 V8 堆快照的方法。然后我们可以使用这个堆来使用 Chrome DevTools在我们的 Electron 应用程序中查找内存泄漏。本教程将演示如何获取 V8 堆快照并将其上传到 Chrome DevTools,以便在 Electron 应用程序中进行进一步检查。

我们假设您熟悉上述链接中介绍的先决条件。为了让 Electron 正常工作,需要在系统中预装nodenpm。

  • 项目结构:

项目结构

示例:按照在 ElectronJS 中拖放文件中给出的步骤设置基本的 Electron 应用程序。复制文章中提供的main.js文件和index.html文件的样板代码。还要执行 package.json文件中提到的必要更改以启动电子应用程序。我们将继续使用相同的代码库构建我们的应用程序。设置 Electron 应用程序所需的基本步骤保持不变。

包.json:

{
  "name": "electron-snapshot",
  "version": "1.0.0",
  "description": "Snapshot of Electron",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [
    "electron"
  ],
  "author": "Radhesh Khanna",
  "license": "ISC",
  "dependencies": {
    "electron": "^8.3.0"
  }
}

根据项目结构创建资产文件夹。我们将使用assets文件夹作为默认路径来存储应用程序生成的 V8 堆快照文件。 V8 堆快照文件的文件扩展名是.heapsnapshot
输出:此时,我们的基本电子应用程序已设置。启动应用程序后,我们应该会看到以下结果。

Electron 中的堆快照: BrowserWindow实例和webContents属性是Main Process 的一部分。为了在Renderer Process 中导入和使用BrowserWindow ,我们将使用 Electron远程模块。

  • index.html :在该文件中添加以下代码段。 Create V8 Heap Snapshot按钮还没有任何与之相关的功能。
html

  Create a Snapshot in Electron


javascript
const electron = require('electron')
const path = require('path')
  
// Importing BrowserWindow using Electron remote
const BrowserWindow = electron.remote.BrowserWindow;
  
let win = BrowserWindow.getFocusedWindow();
  
// let win = BrowserWindow.getAllWindows()[0];
const filepath = path.join(__dirname, '../assets/snap.heapsnapshot')
  
var snap = document.getElementById('snap');
snap.addEventListener('click', (event) => {
    win.webContents.takeHeapSnapshot(filepath)
        .then(console.log('V8 HeapSnapshot taken Successfully'))
        .catch(err => {
            console.log(err);
        });
});


  • index.js :在该文件中添加以下代码段。

javascript

const electron = require('electron')
const path = require('path')
  
// Importing BrowserWindow using Electron remote
const BrowserWindow = electron.remote.BrowserWindow;
  
let win = BrowserWindow.getFocusedWindow();
  
// let win = BrowserWindow.getAllWindows()[0];
const filepath = path.join(__dirname, '../assets/snap.heapsnapshot')
  
var snap = document.getElementById('snap');
snap.addEventListener('click', (event) => {
    win.webContents.takeHeapSnapshot(filepath)
        .then(console.log('V8 HeapSnapshot taken Successfully'))
        .catch(err => {
            console.log(err);
        });
});

win.webContents.takeHeapSnapshot(file path) Instance 方法简单地获取应用程序内存的 V8 堆快照并将其保存到给定的文件路径。此 Instance 方法返回一个Promise并在给定文件路径成功创建快照文件时解析它。它接受以下参数。

  • filepath: String此参数不能为空。它指定了我们要保存生成的堆快照文件的文件路径。在我们的代码中,我们使用路径模块将生成的堆快照文件连同文件名保存到资产文件夹中。

要在Renderer Process 中获取当前BrowserWindow实例,我们可以使用 BrowserWindow对象提供的一些静态方法。

  • BrowserWindow.getAllWindows():此方法返回活动/打开的BrowserWindow实例的数组。在这个应用程序中,我们只有一个活动的BrowserWindow实例,它可以直接从 Array 中引用,如代码所示。
  • BrowserWindow.getFocusedWindow():此方法返回在应用程序中聚焦的 BrowserWindow 实例。如果未找到当前 BrowserWindow 实例,则返回null 。在此应用程序中,我们只有一个活动的BrowserWindow实例,可以使用此方法直接引用它,如代码所示。

输出:启动应用程序后,我们应该会看到以下结果。

snap.heapsnapshot

snap.heapsnapshot文件只是一组随机数字。为了理解这个文件,我们需要将它上传到 Chrome DevTools,以便我们可以评估它的内存泄漏。按照给定的步骤将此文件上传到 Chrome Devtools。

  • 第 1 步:在 Electron 应用程序中,启动 Chrome DevTools,以防它们在应用程序启动时被禁用。我们可以使用键盘快捷键Ctrl+Shift+I 启动。在我们的代码中,我们使用main.js文件中指定的 webContents属性的 win.webContents.openDevTools()实例方法在应用程序启动时默认启用它们。
  • 第 2 步:在 DevTools 中,转到Memory选项卡,然后在Select profiling type 中,选择Heap snapshot选项。之后,单击加载按钮。这应该打开一个本机文件系统对话框。

  • 第 3 步:导航到我们存储.heapsnapshot文件的位置,然后单击Open 。这将上传文件,我们现在可以在 Chrome DevTools 中查看它。单击文件以查看应用程序的统计信息。

输出: 注意:我们也可以使用process对象的process.takeHeapSnapshot(filePath)方法来创建Electron应用的V8 Heap Snapshot文件。 Electron 中的process对象是 NodeJS process对象的扩展,它提供了可以在 Electron 应用程序中使用的额外的各种 Instance 方法和属性。