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

简介: 造成内存泄露的根本原因就是我们写的代码中存在某些对象长期占用内存,得不到释放,且这个对象占用的内存会逐步增加,导致 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

共勉-寄语


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

目录
相关文章
|
3月前
|
存储 缓存 Java
优化Java代码中的内存使用:使用WeakHashMap解决内存泄漏问题
在Java应用程序中,内存泄漏是一个常见的问题,尤其是在处理大量对象时。本文将介绍如何使用WeakHashMap数据结构来解决内存泄漏问题,通过示例代码演示其在实际项目中的应用,从而提高Java代码的性能和可靠性。
|
3月前
|
Rust 安全 编译器
Rust中的生命周期与借用检查器:内存安全的守护神
本文深入探讨了Rust编程语言中生命周期与借用检查器的概念及其工作原理。Rust通过这些机制,在编译时确保了内存安全,避免了数据竞争和悬挂指针等常见问题。我们将详细解释生命周期如何管理数据的存活期,以及借用检查器如何确保数据的独占或共享访问,从而在不牺牲性能的前提下,为开发者提供了强大的内存安全保障。
|
3月前
|
Linux
linux 常用内存检查命令
linux 常用内存检查命令
65 0
|
3月前
|
存储 数据可视化 C++
提高代码效率的6个Python内存优化技巧
当项目变得越来越大时,有效地管理计算资源是一个不可避免的需求。Python与C或c++等低级语言相比,似乎不够节省内存。 但是其实有许多方法可以显著优化Python程序的内存使用,这些方法可能在实际应用中并没有人注意,所以本文将重点介绍Python的内置机制,掌握它们将大大提高Python编程技能。
185 0
|
3月前
|
IDE Linux 开发工具
内存泄漏检测工具Valgrind:C++代码问题检测的利器(一)
内存泄漏检测工具Valgrind:C++代码问题检测的利器
999 0
|
3月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之idea本地测试代码,要增大 Flink CDC 在本地 IDEA 测试环境中的内存大小如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
3月前
|
存储 C++
webserver--Buffer类实现内存缓冲区读写(全代码)
webserver--Buffer类实现内存缓冲区读写(全代码)
|
26天前
|
存储 监控 安全
JVM内存问题之如何比较不同时间点的pmap输出以检查新增或变大的内存段
JVM内存问题之如何比较不同时间点的pmap输出以检查新增或变大的内存段
|
27天前
|
Java 运维
开发与运维内存问题之触发Full GC,类加载检查如何解决
开发与运维内存问题之触发Full GC,类加载检查如何解决
18 0
|
30天前
|
存储 Rust JavaScript
Rust 问题之TypeScript 代码,变量 s 存储在栈内存中还是堆内存中如何解决
Rust 问题之TypeScript 代码,变量 s 存储在栈内存中还是堆内存中如何解决