nodeJs之内存管理

在一般的后端语言中,基本的内存使用上基本没有什么限制,但是在nodeJs中却只能使用部分内存。在64位系统下位约为1.4G,在32位系统下约为0.7G,造成这个问题的主要原因是因为nodeJs基于V8构建,V8使用自己的方式来管理和分配内存,这一套管理方式在浏览器端使用绰绰有余,但是在nodeJs中这却限制了开发者,在应用中如果碰到了这个限制,就会造成进程退出。

戴着脚铐跳舞

在服务端,假如将一个2G的文本文件读到内存中,node进程就会进程崩溃,虽然这种情况不常见,但是开发时候也只能小心翼翼,该如何解决呢?

暴力加内存

在启动node进程的时候,可以调整内存大小。

node --max-old-space-size=1700 test.js // 单位为MB
node --max-new-space-size=1024 test.js // 单位为KB

这个在初始化进程的时候就生效,而且不能动态扩容,一般用来扩充内存,以免稍微多一些内存就崩溃。

合理利用内存

V8限制内存用量,主要是因为V8垃圾回收机制的设计。也正是因为垃圾回收机制,我们才不需要像c++那样手动回收。

在V8中,JavaScript的对象是分配在堆内存中,使用process.memoryUsage()可以查看当前内存使用状态。现在内存有了最大的限制,那么我们写代码的时候就要额外注意了,要避免滥用内存。

1.及时释放全局变量

global.a = {name: 'a object'};
console.log(global.a); // 全局变量不会再用到
global.a = undefined; //释放该对象
  1. 合理使用闭包,及时释放闭包函数的引用。

在启动node进程时带上--trace_gc会在V8进行垃圾回收的时候打印日志,可以帮助我们观察程序内部垃圾回收的情况。

内存泄漏

内存泄漏的实质就是应该被垃圾回收的对象出现意外,没有被回收,变成常驻于内存中的对象。

通常造成内存泄漏的原因有如下几个:

  1. 使用内存进行缓存

  2. 队列消费不及时

  3. 作用域未释放

谨慎使用缓存

缓存和之前说的全局变量其实是一回事,平时前端JavaScript使用缓存的场景可能是因为api请求慢,于是声明一个全局变量来缓存数据,如果有缓存就不用再发请求了,节约了时间。但是在nodeJs中,缓存并非物美价廉。

lodash的memoize方法,提供了一种缓存策略,利用一个map的键值对来缓存数据

function memoize(func, resolver) {
  if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
    throw new TypeError('Expected a function')
  }
  const memoized = function(...args) {
    const key = resolver ? resolver.apply(this, args) : args[0]
    const cache = memoized.cache

    if (cache.has(key)) {
      return cache.get(key)
    }
    const result = func.apply(this, args)
    memoized.cache = cache.set(key, result) || cache
    return result
  }
  memoized.cache = new (memoize.Cache || MapCache)
  return memoized
}

这种方法如果不做限制,或导致缓存对象过大,一直占用在内存中,使用需谨慎。

关注队列

node底层的事件循环,会不停查看是否有事件待处理,如果有的话,就取出事件以及相关回调函数,如果有回调函数则执行。

事件循环一个典型的生产者/消费者的形式,异步I/O是事件的生产者,事件循环就是消费者。大部分时候消费速度都是大于生产速度的,但当生产速度大于消费速度的时候,事件会产生堆积,回调函数中的作用域不会得到释放,于是产生了内存泄漏。

例如现在往数据库插入100W条数据,数据库建立在文件系统之上,写数据效率很慢,很容易产生过多事件等待处理,这时候内存泄漏就无法避免了。

解决方案:

  1. 监控队列长度

  2. 为异步请求加上超时机制。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 因为node绝大多数时间都是运行在后端的服务器程序,因此,需要精确控制内存。在以前,js程序员不需要控制内存...
    白昔月阅读 5,704评论 5 11
  • 原文链接:BlueSun | NodeJS中被忽略的内存 如朴灵说过,Node对内存泄露十分敏感,一旦线上应用有成...
    JC_Huang阅读 11,171评论 4 5
  • 随/奶泡 走在去医院的路上,太阳烈的有些扎眼,但这并没有影响我的心情。 作为一名医生,一瞬间可以很骄傲,一瞬间可以...
    奶泡有点甜阅读 338评论 0 1
  • 本文由币乎社区(bihu.com)内容支持计划赞助 不管你有没有关注数字货币,只要你平时看新闻,“比特币”一定出现...
    Running悠阅读 1,485评论 0 0
  • 刘娜 焦点解决网络初级九期 驻马店 2018~03~06 坚持分享第10天 今天抽空看看书,有关太极图的启发摘录如...
    洋帆起航阅读 334评论 0 0