代码层面
- 优化数据结构:
- 避免不必要的对象创建:例如在循环中尽量复用已有的对象,而不是每次都创建新对象。比如:
// 不好的做法
function createArray() {
let arr = [];
for (let i = 0; i < 1000; i++) {
arr.push({value: i});
}
return arr;
}
// 好的做法
function createArray() {
let arr = [];
let obj = {};
for (let i = 0; i < 1000; i++) {
obj.value = i;
arr.push(obj);
obj = {};
}
return arr;
}
- 合理选择数据结构:根据实际业务场景选择合适的数据结构。如果需要频繁查找,
Map
或 Set
可能比数组更合适,因为它们的查找复杂度为O(1),而数组查找复杂度为O(n)。例如:
// 使用数组查找
let arr = [1, 2, 3, 4, 5];
let index = arr.indexOf(3);
// 使用Set查找
let set = new Set([1, 2, 3, 4, 5]);
let hasValue = set.has(3);
- 及时释放引用:
- 手动解除引用:当对象不再使用时,手动将其引用设置为
null
,以便垃圾回收器可以回收其内存。例如:
let largeObject = {
data: new Array(1000000).fill(1)
};
// 使用完 largeObject 后
largeObject = null;
- 事件监听器管理:确保在不再需要事件监听器时,及时移除它们。例如:
const eventEmitter = require('events').EventEmitter;
let emitter = new EventEmitter();
function listener() {
console.log('Event occurred');
}
emitter.on('event', listener);
// 不再需要监听时
emitter.off('event', listener);
- 流处理:
- 使用可读流和可写流:对于处理大量数据,如文件读取或网络数据传输,使用流可以避免一次性将大量数据加载到内存中。例如:
const fs = require('fs');
const readableStream = fs.createReadStream('largeFile.txt');
const writableStream = fs.createWriteStream('newFile.txt');
readableStream.pipe(writableStream);
- 优化函数作用域:
- 避免闭包造成的内存泄漏:确保闭包中引用的对象在不再需要时能够被正确释放。例如:
function outer() {
let largeArray = new Array(1000000).fill(1);
return function inner() {
// 如果这里不再使用 largeArray,应该将其设置为 null
// largeArray = null;
return largeArray.length;
};
}
let innerFunc = outer();
// 如果 innerFunc 后续不再使用,应该手动解除对 largeArray 的引用
innerFunc = null;
系统配置层面
- 调整Node.js堆内存大小:
- 增加堆内存:可以通过
--max-old-space-size
选项来增加V8引擎的老生代内存大小。例如,将老生代内存大小设置为2048MB:
node --max-old-space-size=2048 app.js
- 动态调整:根据应用的实际运行情况,动态调整堆内存大小,以平衡内存使用和性能。
- 优化垃圾回收算法:
- 选择合适的垃圾回收算法:V8引擎提供了不同的垃圾回收算法,如标记 - 清除(Mark - Sweep)、标记 - 整理(Mark - Compact)等。可以通过
--expose-gc
选项结合 global.gc()
手动触发垃圾回收,并根据应用特点选择合适的算法。例如:
// 在代码中手动触发垃圾回收
const v8 = require('v8');
v8.getHeapStatistics();
global.gc();
v8.getHeapStatistics();
- 监控与调优:
- 使用Node.js内置工具:利用
node --inspect
结合Chrome DevTools进行内存分析,查找内存泄漏点和性能瓶颈。
- 使用外部工具:如
Node.js Process Manager (PM2)
,它可以监控应用的内存使用情况,并在内存过高时自动重启应用。例如:
pm2 start app.js --watch
pm2 monit