Skip to content

electron 内存泄漏排查

分享 electron 内存泄漏排查并修复 - 原因竟然是 console.log 打印了内存 buffer

一、通过任务管理器查看内存是否自动回收

先了解都有哪些进程 - 请查看electron-默认有几个进程

  1. 打印 主进程 id
js
console.log("[main Process ID:]", process.pid);
console.log("[main Process Type:]", process.type);
  1. 打印渲染进程 id
js
newWindow.webContents.on("did-finish-load", () => {
  console.log(`[newWindow ${id} is ready]`);

  // 输出渲染进程的 PID
  const rendererPID = newWindow.webContents.getOSProcessId();
  console.log(`Renderer process ID for window ${id}: ${rendererPID}`);
});

alt text

  1. 任务管理器观察对应的进程 id 的内存情况 来分析时哪一个进程出现了内存增长没有回收的问题

alt text

二、通过不断重复操作 查看对应的进程是否出现只增不减的情况

  1. 找到对应的进程 - 出现只增不减的情况

  2. 通过增加、或减少代码来判断是那一段代码出现了问题

警告

特别注意 console.log 是会导致内存泄漏的

请判断下面的代码哪一行可能出现内存泄漏?

js
const { contextBridge, ipcRenderer } = require("electron");
const sharedMemory = require("../shared_memory/index.js"); 
window.electronAPI = {
  getImageData(length, mySharedMemoryKey) {
    console.time("读取图片完整耗时");
    console.time("创建或者打开内存");
    sharedMemory.createOrOpenSharedMemory(mySharedMemoryKey, length); 
    console.timeEnd("创建或者打开内存");
    console.time("读取内存");
    const imageData = sharedMemory.readFromSharedMemory(mySharedMemoryKey); 

    console.log("mySharedMemoryKey", mySharedMemoryKey);
    console.log("imageData", imageData); 
    console.timeEnd("读取内存");
    console.time("关闭内存");
    sharedMemory.closeSharedMemory(mySharedMemoryKey); 
    console.timeEnd("关闭内存");
    console.log("imageData", imageData.length, Date.now());
    console.timeEnd("读取图片完整耗时");
    return imageData;
  },
};
答案

7 行、13 行和 16 行。

  1. 第 7 行:sharedMemory.createOrOpenSharedMemory(mySharedMemoryKey, length);

    • 如果共享内存没有正确关闭或释放,可能导致内存泄漏。需要确保 createOrOpenSharedMemory 正确管理资源,并且关闭操作在任何情况下都会执行。
  2. 第 13 行:const imageData = sharedMemory.readFromSharedMemory(mySharedMemoryKey);

    • 如果从共享内存读取的数据量很大,并且在日志中输出整个对象,可能导致内存泄漏,尤其是 console.log 会保留对大数据对象的引用,直到垃圾回收器回收该引用。
  3. 第 16 行:console.log("imageData", imageData);

    • 在控制台输出大量数据(特别是 imageData 是大对象时)可能导致内存泄漏,因为控制台会保留对数据的引用,使垃圾回收无法及时回收这部分内存。

1. 默认内存大小:

alt text

2. 重复几次后,这两个进程内存没有减少

alt text

3. 修复:删除代码中的 console.log("imageData", imageData);

js
window.electronAPI = {
  getImageData(length, mySharedMemoryKey) {
    console.time("读取图片完整耗时");
    console.time("创建或者打开内存");
    sharedMemory.createOrOpenSharedMemory(mySharedMemoryKey, length);
    console.timeEnd("创建或者打开内存");
    console.time("读取内存");
    const imageData = sharedMemory.readFromSharedMemory(mySharedMemoryKey);

    // console.log("mySharedMemoryKey", mySharedMemoryKey);
    // console.log("imageData", imageData);
    // console.timeEnd("读取内存");
    // console.time("关闭内存");
    sharedMemory.closeSharedMemory(mySharedMemoryKey);
    // console.timeEnd("关闭内存");
    // console.log("imageData", imageData.length, Date.now());
    // console.timeEnd("读取图片完整耗时");
    return imageData;
  },

4. 修改后,重复几次截屏操作,几秒后,内存自动将回去了

说明内存被正常回收了!,这才是正常的应用进程

alt text