【问题标题】:Can you spot the memory leak in this node.js function?你能发现这个 node.js 函数中的内存泄漏吗?
【发布时间】:2020-10-11 19:36:51
【问题描述】:

我部署的应用程序有一个函数,只要调用app.get("/") 路由,或者当用户向数据库添加或删除文件时,它就会调用数据库。调用此函数时,我的 Web 主机限制了我的服务,因为它超出了我的内存分配,导致我的一个 npm 包(尖锐)出现故障,没有可用于处理图像的处理器线程。

我研究了我的网络主机提供的指标,但除了告诉我发生了错误之外,它并没有显示内存使用量有多大或在哪里。使用 Chrome DevTools 任务管理器,我可以看到实时 javascript 内存实际上确实在应用程序运行时缓慢增加,但并不比我查看过的其他网页多。

我在该领域没有导师,在对内存泄漏、导致它们的原因以及如何解决它们进行了详尽的研究之后,我感到迷茫和困惑,但我相信我已经将其范围缩小到问题的罪魁祸首。我只是不知道从这里做什么。

这里是有问题的函数:

let artWorks = [];

async function listFiles() {
  artWorks = [];   //clears the array if it has content
  const [files] = await storage.bucket(bucketName).getFiles();    //call for url names of files in DB
  files.forEach(file => {   //loops through all files and pushes them to the array, separating the URL string into usable data
    function splitStr(str) {
      var string = str.split("/");
      artWorks.push(
        {
          imgCategory: string[0],
          subCat: string[1].replace(/-/g, ' '),
          imgSrc: bucket + file.name,
          thumbnail: thumbBucket + file.name.split('.')[0] + "-thumb.jpg",
          alt: string[2]
        });
    }
    var str = file.name;
    splitStr(str);
  });
  console.log("files listed");
}

artWorks 数组是整个应用程序的关键。每个路由都使用这个数组的内容来填充 ejs 模板页面。用户添加或删除文件后,将再次调用 listFiles() 函数以重新填充数组。

我没有注意到性能下降,如果不是因为我的网络主机限制了我的内存,我永远不会知道有泄漏。请为我提供指导,希望不要过多地涉及术语,但是像我这样的新开发人员可以理解的术语。

【问题讨论】:

  • 如果到处使用artWorks,任何使用它的代码都可能因为持有“旧”数组而导致内存泄漏。制作堆快照并检查究竟是什么保留了对象。
  • Chrome devtools 测量客户端内存使用情况,这与服务器端代码无关。数组中有多少个文件?
  • @GuyIncognito 文件数量不定,但平均约为 100 个。每个文件代表数组中的一个对象,其中键:值对显示在函数中。
  • 不是内存泄漏,但是将 splitStr 放入 forEach 会给内存管理器带来更多压力。您基本上会在 1 时为每个文件创建一个新函数。
  • 再次,该屏幕截图显示了您的浏览器的内存使用情况。它与 Node.js 代码无关。您需要在服务器上拍摄快照。

标签: javascript node.js memory-leaks heap-memory heap-dump


【解决方案1】:

请注意,您在每次迭代中都声明了 splitStr 函数。 我给你写了一个小建议,希望能以更简洁的方式阅读这段代码 sn-p。

希望你喜欢。

 const filesMapper = ({name}) => {
    const string = name.split('/')
    return { 
       imgCategory: string[0],
       subCat: string[1].replace(/-/g, ' '),
       imgSrc: bucket + name,
       thumbnail: thumbBucket + name.split('.')[0] + "-thumb.jpg",
       alt: string[2]
    }
}

async function listFiles() {
    const [files] = await storage.bucket(bucketName).getFiles(); 

    return files.map(filesMapper)
  });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 2011-02-20
    • 2013-08-12
    相关资源
    最近更新 更多