# 代码优化:内存管理优化

减少内存使用会提供服务器性能,如果有内存泄露会大大降低服务器性能。

# 垃圾回收

Javascript引擎会记录创建的所有变量,并将它们管理起来。隔一段时间,就会去定时清理没有使用的Javascript变量。完成内存的回收,释放。通过垃圾回收机制完成了Javascript变量,从出生到死亡的过程。

每个Javascript引擎的垃圾回收机制是不一样的。

# V8引擎垃圾回收

  • 新生代:容量小,垃圾回收触发频率高,垃圾回收更快
  • 老生代:容量大,垃圾回收触发频率低,垃圾回收更慢

V8引擎会把堆内存分为新生代和老生代。

所有新创建的Javascript变量,都会先放入 新生代 这个内存区域。在改区域快要满时,就会执行一次快速的垃圾回收。把没用的变量清理掉,腾出内存空间给新创建的变量。

如果 新生代 这个内存区域,如果某些变量经过几次垃圾回收都没有被清理,那么这些变量就会进入 老生代

老生代 这个内存区域容量更大,垃圾回收的触发频率低。

# 比较典型的内存泄漏

# 不恰当的全局缓存导致的泄漏

'use strict';
const easyMonitor = require('easy-monitor');
const express = require('express');
const app = express();

const _cached = [];

app.get('/arr', function arrayLeak(req, res, next) {
	//泄漏代码
    _cached.push(new Array(1000000));
    res.send('Hello World');
});

app.listen(8082);

_cached 保存了缓存但是没有清除,那么就会引起泄漏。

# 减少内存使用

节省内存的最好方式就是:

  • 使用池

# NodeJS Buffer 的内存分配策略

Buffer 对象的内存分配不是在V8的堆内存中,而是在Node的C++层面实现内存的申请。因为处理大量数据不能采用需要一点内存就像操作系统申请一点内存的方式,这样大量内存的申请,对操作系统有很大的压力。

Buffer模块会预分配一个大小为 Buffer.poolSize 8k的内部 Buffer 实例作为快速预分配池。

NodeJS 在创建小于 8k 的Buffer时,默认会从预分配的 8k 分配池中截取一段内存空间给小的Buffer的使用。如果,后续还有小的Buffer创建,又会从预分配的分配池中截取一段内存空间给新的小的Buffer的使用,以此类推。

但是,一旦有一个小的Buffer,预分配的 8k 分配池中剩余的空间不够用了,就又会申请一个 8k 分配池。用于这个新的小的Buffer使用。

如果,后续有一个小的Buffer内存空间,适配初始预分配的大小为 Buffer.poolSize 8k的内部 Buffer 剩余的空间,那么该剩余空间就会给该小的Buffer使用。

在此期间,如果有Buffer被销毁,空间被释放。对应的分配池的内存又可以提供给新的小的Buffer使用。

# 总结

通过上面的算法,可以避免频繁申请内存空间,优化了内存使用 ,节省了内存,减少了性能的消耗。

# 參考

更新时间: 6/29/2020, 6:30:01 PM