检查自己的代码是否存在内存泄露

简介: 造成内存泄露的根本原因就是我们写的代码中存在某些对象长期占用内存,得不到释放,且这个对象占用的内存会逐步增加,导致 v8 无法回收,从而造成的服务的异常和不稳定,甚至是服务的中断和崩溃。

内存泄露怎样产生的


造成内存泄露的根本原因就是我们写的代码中存在某些对象长期占用内存,得不到释放,且这个对象占用的内存会逐步增加,导致 v8 无法回收,从而造成的服务的异常和不稳定,甚至是服务的中断和崩溃。

内存泄露在浏览器端不是很敏感,如果是在服务端就不得不考虑这个问题。因为内存泄露具有潜伏性,而且非常不明显,在时间的推移下才能慢慢的发现异常,内存占用不断增加,等到发现的时候已经来不及采取有效的解决方案进行处理,只能重启服务来暂时处理这种风险。所以在服务上线前就需要进行有效的检测。

node-headdump


本文主要来说下使用 node-headdump进行内存泄露的定位。

该模块主要是一个抓取当前内存的快照(存储为JSON文件)信息,包括所有的字符,对象和函数所占用内存的情况。

官方地址:https://github.com/bnoordhuis/node-heapdump

这个模块的使用非常简单。

  • 安装
npm install heapdump
//如果遇到权限问题, 可以使用
npm install heapdump --unsafe-perm
  • 在代码中引入
const heapdump = require('heapdump');

既然要使用 node-heapdump 对内存泄露进行定位,我需要先构造一个有问题的代码,然后最终已服务的形式启动。

下面代码中,变量 arr会常驻内存,无法释放,在服务器每次接收请求的时候都会向 arr写入一条数据

//内存泄露定位
const http = require('http');
const heapdump = require('heapdump');
const arr = [];
const runleak = function () {
    arr.push('node leak'+Math.random());
}
http.createServer((req,res)=>{
    //模拟大内存对象
    for(var i=0;i<100000;i++){
        runleak();
    }
    // 创建快照 方法1 通过代码创建快照
    heapdump.writeSnapshot(Date.now() + '.heapsnapshot');
    //end
    res.writeHead(200,{'content-type':'text/plain'});
    res.end('hello , test node leak');
}).listen(9527);
console.log('server 9527 start... http://localhost:9527');

创建快照的方式有两种

  • 代码写入

可以设置写入的时机和快照存储的位置。

heapdump.writeSnapshot(function(err, filename) {
  console.log('dump written to', filename);
});
  • 命令写入

快照将会存储在文件目录下以 heapdump-<sec>.<usec>.heapsnapshot的格式存放.

$ kill -USR2 <pid>

首先需要查找到当前的进程 id

$ ps aux | grep node
//或者根据端口号查找
$ lsof -i tcp:9527

查看分析


其实生成的快照就是一个 json文件,可以通过Chrome的开发者工具进行查看。

  • f12打开开发者工具
  • 打开 Memory面板
  • Profiles上右键 ,点击load...,打开快照文件

4fc40078863d9325bc6a86877ac94011_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

加载快照文件后就能看到大量占用内存的数据,然后根据这些信息找到存在内存泄露的代码。

529df5704c8183af84cd44214175c945_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

其他工具


下面是一些常见的用于排查 node 应用的内存泄露工具,有兴趣的可以了解下

  • v8-profiler
  • node-mtrace
  • dtrace
  • node-memwatch

共勉-寄语


当才华还撑不起你的野心的时候,就应该静下心来学习。当能力还驾驭不了你的目标的时候,就应该沉下心来历练。问问自己,想要怎样的人生。

目录
相关文章
|
1月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
251 6
|
19天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
46 5
|
20天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
49 1
|
1月前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
1月前
|
存储 JavaScript 前端开发
如何优化代码以避免闭包引起的内存泄露
本文介绍了闭包引起内存泄露的原因,并提供了几种优化代码的策略,帮助开发者有效避免内存泄露问题,提升应用性能。
|
7月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之idea本地测试代码,要增大 Flink CDC 在本地 IDEA 测试环境中的内存大小如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
109 1
|
7月前
|
存储 C++
webserver--Buffer类实现内存缓冲区读写(全代码)
webserver--Buffer类实现内存缓冲区读写(全代码)
|
4月前
|
存储 缓存 JSON
一行代码,我优化掉了1G内存占用
这里一行代码,指的是:String.intern()的调用,为了调用这一行代码,也写了几十行额外的代码。
|
4月前
|
缓存 Java
Java内存管理秘籍:掌握强软弱幻四大引用,让代码效率翻倍!
【8月更文挑战第29天】在Java中,引用是连接对象与内存的桥梁,主要分为强引用、软引用、弱引用和幻象引用。强引用确保对象生命周期由引用控制,适用于普通对象;软引用在内存不足时可被回收,适合用于内存敏感的缓存;弱引用在无强引用时即可被回收,适用于弱关联如监听器列表;幻象引用需与引用队列配合使用,用于跟踪对象回收状态,适用于执行清理工作。合理使用不同类型的引用车可以提升程序性能和资源管理效率。
49 4
|
4月前
|
前端开发 JavaScript Java
揭开 JavaScript 垃圾回收的秘密——一场与内存泄漏的生死较量,让你的代码从此焕然一新!
【8月更文挑战第23天】本文通过多个实例深入探讨了JavaScript中的垃圾回收机制及其对应用性能的影响。首先介绍了基本的内存管理方式,随后分析了变量不再使用时的回收过程。接着,通过事件监听器未被移除及全局变量管理不当等场景展示了常见的内存泄漏问题。最后,文章介绍了使用`WeakRef`和`FinalizationRegistry`等现代API来有效避免内存泄漏的方法。理解并运用这些技术能显著提升Web应用的稳定性和效率。
97 0