Node.js 性能优化实战:从理论到实践

前言

Node.js 以其高性能和非阻塞 I/O 特性著称,但要充分发挥其性能潜力,需要我们深入理解其运行机制并采用合适的优化策略。

事件循环机制

理解事件循环是优化 Node.js 应用的基础:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 同步代码优先执行
console.log('1');

// setImmediate 在 I/O 回调之后执行
fs.readFile('test.txt', () => {
console.log('2');
setImmediate(() => console.log('3'));
});

// process.nextTick 在当前阶段完成后、下个阶段前执行
process.nextTick(() => console.log('4'));

setTimeout(() => console.log('5'), 0);

// 输出顺序: 1, 4, 5, 2, 3

内存管理

避免内存泄漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 常见内存泄漏场景
class DataCache {
constructor() {
this.cache = new Map();
}

add(key, value) {
// 问题:永不过期的缓存
this.cache.set(key, value);
}

// 解决方案:使用 WeakMap 或添加过期机制
}

// 推荐:使用 LRU Cache
const LRU = require('lru-cache');
const cache = new LRU({
max: 500,
maxAge: 1000 * 60 * 5 // 5分钟后过期
});

V8 垃圾回收

了解 V8 的垃圾回收机制有助于写出更高效的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 避免大对象频繁创建
// 不好
function processItems(items) {
return items.map(item => ({ ...item, processed: true }));
}

// 好:使用对象池
const objectPool = [];

function getObject() {
return objectPool.pop() || {};
}

function releaseObject(obj) {
objectPool.push(obj);
}

性能监控

使用 Clinic.js

1
2
3
4
5
6
7
8
# 安装
npm install -g clinic

# 性能分析
clinic doctor -- node server.js

# CPU 分析
clinic flame -- node server.js

关键指标

1
2
3
4
5
6
7
8
9
const v8 = require('v8');
const os = require('os');

console.log({
heapStatistics: v8.getHeapStatistics(),
heapSpaceStatistics: v8.getHeapSpaceStatistics(),
cpuUsage: process.cpuUsage(),
memoryUsage: process.memoryUsage()
});

异步优化

Promise.all vs 串行执行

1
2
3
4
5
6
7
8
9
10
11
12
13
// 串行:总时间 = sum(各请求时间)
async function serialFetch(urls) {
const results = [];
for (const url of urls) {
results.push(await fetch(url));
}
return results;
}

// 并行:总时间 = max(各请求时间)
async function parallelFetch(urls) {
return Promise.all(urls.map(url => fetch(url)));
}

流式处理大文件

1
2
3
4
5
6
7
8
9
10
11
const fs = require('fs');
const zlib = require('zlib');

// 流式压缩,内存占用低
const readStream = fs.createReadStream('largefile.txt');
const writeStream = fs.createWriteStream('largefile.txt.gz');
const gzip = zlib.createGzip();

readStream
.pipe(gzip)
.pipe(writeStream);

集群模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
const numCPUs = os.cpus().length;

for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}

cluster.on('exit', (worker, code) => {
console.log(`Worker ${worker.process.pid} 退出`);
cluster.fork(); // 保持工作进程数量
});
} else {
const app = require('./app');
app.listen(3000);
}

总结

Node.js 性能优化是一个系统工程,需要从多个维度入手:

  1. 深入理解事件循环机制
  2. 合理管理内存,避免泄漏
  3. 建立完善的监控体系
  4. 采用异步编程最佳实践
  5. 根据场景选择合适的架构模式