优化 Node.js 性能:检测内存泄漏和高 CPU 使用率

news2024/12/26 23:42:07

优化 Node.js 性能:检测内存泄漏和高 CPU 使用率

Node.js 是一种流行的 JavaScript 运行时,以其速度、性能和可扩展性而闻名。然而,即使是优化和编写得非常好的 Node.js 应用程序也可能会遇到性能问题,例如内存泄漏和 CPU 使用率过高。分析是帮助识别和解决这些性能瓶颈的关键过程。在本教程中,我们将介绍用于分析 Node.js 应用程序的最佳实践和工具,包括如何检测内存泄漏和高 CPU 使用率。

分析的重要性

分析 Node.js 很重要,它可以帮助我们了解应用程序如何使用 CPU、内存和 I/O 等资源并识别性能瓶颈。分析可以提供有价值的信息,可用于优化应用程序、减少完成任务所需的时间、减少内存使用并提高整体响应能力。

  • 优化性能 - 分析有助于识别应用程序中的性能瓶颈,例如响应时间慢和 CPU 使用率高。通过解决这些瓶颈,我们可以提高应用程序的整体性能。
  • 提高稳定性 - 分析可帮助我们识别应用程序中的稳定性问题,例如内存泄漏。通过解决这些问题,我们可以提高应用程序的整体稳定性。
  • 节省资源 - 分析可帮助我们识别应用程序中的资源使用情况,例如内存和 CPU 使用情况。通过减少资源使用,我们可以节省成本并提高应用程序的可扩展性。

可使用的工具

Chrome 开发工具

Chrome DevTools 是一款功能强大的 Node.js 应用程序调试和分析工具。它们提供有关应用程序的大量信息,包括内存使用情况、CPU 使用情况、请求计数、响应时间等。要访问 Chrome DevTools,可以通过在终端中键入node --inspect命令来使用命令行界面。

Node Inspector

Node InspectorNode.js 应用程序的强大调试和分析工具。它提供了一个图形用户界面,可以轻松监控我们的应用程序,包括内存使用情况、CPU 使用情况、请求计数、响应时间等。要使用 Node Inspector,可以通过在终端中键入npm install -g node-inspector命令安装。

node-memwatch

node-memwatch是一个 Node.js 模块,可帮助跟踪 Node.js 应用程序中的内存使用情况并检测内存泄漏。它提供了一个API来监视堆大小、堆使用情况和堆中对象的数量,以及跟踪GC(垃圾收集)统计信息。它还提供了用于检测内存泄漏和生成堆快照的工具,可用于识别内存问题的原因。

memwatch.on('leak', function(info) { ... });

v8-profiler

v8-profiler是一个用于分析 Node.js 应用程序的 npm 库。它提供了一个 API,用于使用 V8 JavaScript 引擎的内置分析器来分析 Node.js 运行时中运行的 JavaScript 代码。探查器收集有关 JavaScript 代码执行的信息,例如函数调用计数、函数计时和内存使用情况,可以分析这些信息以识别应用程序中的性能瓶颈和内存泄漏。

该库允许我们启动和停止分析会话、拍摄堆和分析数据的快照,并以人类可读的格式生成分析数据的报告。配置文件数据还可以保存到文件中并加载到可视化工具中以进行进一步分析。

const express = require('express');
const v8Profiler = require('v8-profiler');
const path = require('path');
const fs = require('fs');

const app = express();
const snapshots = new Map();

// 用于获取堆快照
app.get('/api/heap-snapshot', (req, res) => {
  const snapshot = v8Profiler.takeSnapshot();
  const name = snapshot.getHeader().title;
  snapshots.set(name, snapshot);

  res.send({ name });
});

// 用于按名称下载堆快照
app.get('/api/heap-snapshot/:name', (req, res) => {
  const name = req.params.name;
  const snapshot = snapshots.get(name);
  if (!snapshot) {
    return res.status(404).send({ error: 'Snapshot not found' });
  }

  const fileName = `${name}.heapsnapshot`;
  const filePath = path.resolve(__dirname, 'snapshots', fileName);
  snapshot.serialize(
    { write: chunk => fs.appendFileSync(filePath, chunk) },
    () => {
      res.download(filePath, fileName, error => {
        if (error) {
          console.error(error);
        }
        snapshots.delete(name);
      });
    }
  );
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

示例

内存泄漏

以下代码创建一个简单的 HTTP 服务器。

const express = require("express");
const app = express();
let data = [];

app.get("/leak", (req, res) => {
  setInterval(() => {
    data.push(new Array(1000000).join("a"));
  }, 1000);
  res.send("Memory leak started!");
});

app.listen(3000, () => {
  console.log("Server started on port 3000");
});

setInterval函数创建一个包含大量数据的新数组,并每秒将其推送到data数组。问题在于数据永远不会从内存中释放,导致内存使用量持续增加,称为内存泄漏。随着时间的推移,应用程序的内存使用量将会增加,直到最终由于内存不足而崩溃。要修复此内存泄漏,我们需要从内存中删除未使用的数据,例如,通过设置data = []来处理不需要的数据。

要检测内存泄漏,我们可以通过在终端中键入node --inspect命令来使用 Chrome DevToolsChrome DevTools 打开后,我们可以导航到“memory”选项卡并选择Take Heap Snapshot。这将为我们提供内存使用情况的快照。然后,我们可以将此快照与以后的快照进行比较,看看内存使用量是否随着时间的推移而增加。

目的是比较在不同时间点拍摄的两个堆快照,以查看哪些对象在内存中累积。这使我们可以查看哪些对象没有被垃圾收集,并确定是否发生内存泄漏。

在这里插入图片描述

重要的是比较不同时间点拍摄的堆快照以确定是否发生内存泄漏。比较堆快照时,我们除了查找快照之间大小或数量增加的对象外,还应该查看每个对象的参考图,以确定它没有被垃圾收集的原因。在许多情况下,对象之间的循环引用可能会导致内存泄漏,因为对象无法被垃圾收集,因为它们仍然被其他对象引用。

  • Shallow size:这是内存中对象的大小,包括其属性占用的内存以及存储在这些属性中的任何值的大小。
  • Retained size:这是如果对象被垃圾回收将释放的总内存,不仅包括对象本身的浅层大小,还包括该对象引用的所有对象的浅层大小,即使它们不是直接引用的代码的其他部分。

换句话说,对象的保留大小是其浅层大小与所有因该对象引用而无法被垃圾收集的对象的浅层大小之和。此测量可以帮助我们识别占用大量内存的对象,即使它们本身没有很大的浅层大小。

CPU 使用率高

const express = require("express");
const app = express();
function highCPUFunction() {
    let sum = 0;
    for (let i = 0; i < 10000000; i++) {
        sum += Math.pow(Math.sin(i), i);
    }
    return sum;
}
app.get("/high-cpu", (req, res) => {
    const start = Date.now();
    // 执行计算密集型操作
    const result = highCPUFunction();
    const end = Date.now();
    console.log(`Computation took ${end - start}ms`);
    res.send(result);
});
app.listen(3000, () => {
    console.log("Server started on port 3000");
});

上面的代码创建了一个highCPUFunction函数,该函数执行 10M 次迭代的循环。计算完成循环所需的时间并将其记录到控制台。

这种计算密集型操作可能会导致 CPU 使用率较高,因为 CPU 将努力执行循环中的计算。CPU 使用量取决于 CPU 的处理能力和可用系统资源等因素。

导航到Performance选项卡并选择Start profiling,一旦开始分析,我们就可以访问http://localhost:3000/high-cpu,这将开始对应用程序进行分析,并为我们提供 CPU 使用情况的详细视图,包括哪些函数使用最多的 CPU 时间。
在这里插入图片描述

结论

分析是优化 Node.js 应用程序性能、稳定性和可扩展性的重要过程。通过使用 Node.js 内置进程管理器、Chrome DevToolsNode Inspector 等工具,我们可以轻松监控和解决内存泄漏、CPU 使用率过高等性能问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1044244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4K视频一分钟大小是多少?如何转换为其他分辨率?

4K 分辨率是指大约 4,000像素的水平显示分辨率&#xff0c; 4K显示器、电视的分辨率为3840*2160&#xff1b;影院的4K分辨率为40962160。4K视频相较于常见的1080P分辨率更清晰、画面更流畅&#xff0c;然而与之对应的则是文件更大&#xff0c;更占用本地存储内存&#xff0c;在…

距离矢量路由协议RIP(含Cisco模拟器实验命令配置)

距离矢量路由协议RIP(含Cisco模拟器实验命令配置) 简介 距离矢量路由协议&#xff08;Routing Information Protocol, RIP&#xff09;是一种内部网关协议&#xff0c;它位于应用层&#xff0c;使用520 UDP端口。RIP基于距离矢量算法&#xff08;Bellham-Ford&#xff09;根据…

数据探索的新前沿:可视化大屏交互功能

在当今数字化时代&#xff0c;数据和信息是企业成功的关键。可视化大屏已经成为各个行业中数据呈现和决策支持的重要工具。然而&#xff0c;随着技术的发展&#xff0c;用户对于数据可视化的期望也在不断演变。仅仅呈现数据已经不再足够&#xff0c;用户希望能够更深入地与数据…

buildroot中将编译好的库(Qt,tslib)放入嵌入式linux文件系统

首先交叉编译想使用版本的Qt源码&#xff0c;还有tslib库&#xff0c;编译好之后 再次编译buildroot&#xff0c;再编译好的buildroot中会出现output文件夹&#xff0c;然后output文件夹下有target文件夹&#xff0c;这个target文件夹就是将要打包的文件系统&#xff0c;目标目…

Cloudflare分析第二天:解密返回数据

前言 Cloudflare分析第一天&#xff1a;简单的算法反混淆 由上篇for (j "10|8|5|9|1|4|0|2|3|6|7"["split"](|) 可以看到循环的循序 case 6:o (n {},n["msg"] f,n.cc g,hF["VNwzz"](JSON["stringify"](n))["re…

多线程和并发编程(6)—并发编程的设计模式

优雅终止 如何优雅终止线程&#xff1f; 中断线程的思路是使用两阶段法&#xff1a;第一阶段发生中断请求&#xff0c;第二阶段根据中断标识结束线程&#xff1b; public class Test1 {private volatile static boolean interrupted false;public static void main(String[…

生信教程:使用全基因组SNP数据进行ABBA-BABA分析

动动发财的小手&#xff0c;点个赞吧&#xff01; 简介 ABBA BABA 统计&#xff08;也称为“D 统计”&#xff09;为偏离严格的分叉进化历史提供了简单而有力的测试。因此&#xff0c;它们经常用于使用基因组规模的 SNP 数据&#xff08;例如来自全基因组测序或 RADseq&#xf…

monkeyrunner环境搭建和初步用法

一、打开模拟器 运行monkeyrunner之前必须先运行相应的模拟器&#xff0c;不然monkeyrunner无法连接设备。 用Elipse打开Android模拟器或在CMD中用Android命令打开模拟器。这里重点讲一下在CMD中用Android命令打开模拟器 命令&#xff1a;emulator -avd test &#xff08;注…

使用ElementUI结合Vue完善主页的导航菜单和书籍管理以及后台数据分页查询

目录 动态树 数据表 案列 书籍管理 动态树 动态树&#xff08;Dynamic tree&#xff09;是一种数据结构&#xff0c;它可以在树中动态地插入、删除和修改节点。与静态树不同&#xff0c;静态树的节点是固定的&#xff0c;一旦构建完成就无法再进行修改。而动态树可以在运行时…

中间件 - 分布式协调服务Zookeeper

目录 一. 前言 二. 树状结构 2.1. ZNode 2.1.1. stat 2.1.2. ACL 三. NameService命名服务 四. Configuration 配置管理 五. GroupMembers 集群管理 六. 集群三个角色及状态 七. 选举算法 八. Watcher 九. 设计目的 十. 典型使用场景 一. 前言 Zookeeper是一个分布…

Learn Prompt- Midjourney案例:Logo设计

Logo设计是一个充满挑战的任务&#xff0c;因为Logo是品牌重要价值的浓缩。 快速开始​ 直接使用logo design for...来获取灵感。 备注 图像中生成文字在Midjourney中的效果还不是很好&#xff0c;但你可以用Canva编辑图片并替换自己的文字。 在提示中使用那些擅长你所寻找的…

02-Zookeeper实战

上一篇&#xff1a;01-Zookeeper特性与节点数据类型详解 1. zookeeper安装 Step1&#xff1a; 配置JAVA环境&#xff0c;检验环境&#xff1a; java -versionStep2: 下载解压 zookeeper wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.5.8/apache-zookeepe…

大数据安全 | 【实验】仿射加密

文章目录 &#x1f4da;实验目的&#x1f4da;关于仿射加密&#x1f525;使用暴力破解的方式对仿射加密进行破解&#xff0c;还原明文&#x1f525;使用词频统计的方式对仿射加密进行破解&#xff0c;还原明文&#x1f525;在同一运行环境下&#xff0c;对比两种破解方式所需的…

LLM之Colossal-LLaMA-2:Colossal-LLaMA-2的简介、安装、使用方法之详细攻略

LLM之Colossal-LLaMA-2&#xff1a;Colossal-LLaMA-2的简介、安装、使用方法之详细攻略 导读&#xff1a;2023年9月25日&#xff0c;Colossal-AI团队推出了开源模型Colossal-LLaMA-2-7B-base。Colossal-LLaMA-2项目的技术细节&#xff0c;主要核心要点总结如下: >> 数据处…

融合之力:数字孪生、人工智能和数据分析的创新驱动

数字孪生、人工智能&#xff08;AI&#xff09;和数据分析是当今科技领域中的三个重要概念&#xff0c;它们之间存在着紧密的关联和互动&#xff0c;共同推动了许多领域的创新和发展。 一、概念 数字孪生是一种数字化的模拟技术&#xff0c;它通过复制现实世界中的物理实体、…

应用在手机触摸屏中的电容式触摸芯片

触控屏&#xff08;Touch panel&#xff09;又称为触控面板&#xff0c;是个可接收触头等输入讯号的感应式液晶显示装置&#xff0c;当接触了屏幕上的图形按钮时&#xff0c;屏幕上的触觉反馈系统可根据预先编程的程式驱动各种连结装置&#xff0c;可用以取代机械式的按钮面板&…

数据库存储引擎和数据类型详细介绍

目录 一、数据库存储引擎&#xff08;了解&#xff09;1.了解MySQL体系结构2.存储引擎&#xff08;了解&#xff09;2.1.存储引擎的介绍2.2.存储引擎分类2.3.如何选择引擎&#xff1f; 3.事务控制语言(TCL)事务的四个特性(ACID) 二、数据类型&#xff08;了解&#xff09;1.整型…

【文献】TOF标定 Time-of-Flight Sensor Calibration for a Color and Depth Camera Pair

文章目录 Article info.Introduction处理TOF误差Take home messagesResourcesIDEAS Article info. Time-of-Flight Sensor Calibration for a Color and Depth Camera Pair IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE, VOL. 37, NO. 7, JULY 2015 Intr…

(一)连续随机量的生成-加权重采样

加权重采样 import numpy as np import matplotlib.pyplot as plt# Step 1: Generate 10,000 random theta values from U([0, 1]) n 10000 theta_values np.random.rand(n)# Define the function to compute weights for a given theta def compute_weight(theta):return (…

SQLAlchemy列参数的使用和query函数的使用

目录 Column常用参数 代码演示 代码刨析 query函数的使用 基本用法 常见用法示例 查询所有记录 根据条件查询 查询第一条符合条件的记录 查询特定列的值 添加排序规则 使用聚合函数 连接查询 使用filter_by Column常用参数 primary_key&#xff1a;True设置某个字…