Node.js性能优化实战手册
Node.js性能基础
Node.js基于V8引擎,采用事件驱动、非阻塞I/O模型,天然适合高并发场景。但要发挥其最大性能,需要深入理解其机制并进行针对性优化。
性能瓶颈识别
// 使用perf_hooks测量
const { performance, PerformanceObserver } = require('perf_hooks');
// 测量函数执行时间
performance.mark('start');
// ... 代码执行
performance.mark('end');
performance.measure('My Function', 'start', 'end');
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
observer.observe({ entryTypes: ['measure'] });
// 使用console.time
console.time('operation');
// ... 操作
console.timeEnd('operation');
V8优化
优化编译
// V8优化提示
// 1. 保持对象形状一致
// 好
function Point(x, y) {
this.x = x;
this.y = y;
}
// 坏 - 隐藏类改变
function Point(x, y) {
if (x) this.x = x;
if (y) this.y = y;
}
// 2. 避免修改数组类型
// 好
const arr = [1, 2, 3]; // PACKED_SMI_ELEMENTS
// 坏 - 降级为PACKED_ELEMENTS
arr.push('string');
// 3. 单态操作
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height; // 单态
}
}
内存管理
// 查看内存使用
const used = process.memoryUsage();
console.log({
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
external: `${Math.round(used.external / 1024 / 1024)}MB`
});
// 手动触发GC(生产环境禁用)
if (global.gc) {
global.gc();
}
// 内存泄漏检测
const { heapSnapshot } = require('v8');
// 生成堆快照
const snapshot = heapSnapshot.writeHeapSnapshot();
console.log(`Heap snapshot written to ${snapshot}`);
// Set和Map清理
let cache = new Map();
function cleanup() {
for (const [key, value] of cache) {
if (value.expired) cache.delete(key);
}
}
setInterval(cleanup, 60000);
异步优化
Promise优化
// 并行执行
async function fetchAll() {
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments()
]);
return { users, posts, comments };
}
// 错误处理
async function fetchWithRetry(fn, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
}
// 限制并发数
async function limitConcurrency(tasks, limit) {
const results = [];
const executing = [];
for (const task of tasks) {
const p = Promise.resolve().then(() => task());
results.push(p);
if (limit <= tasks.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
}
return Promise.all(results);
}
事件循环优化
// 检查事件循环延迟
const { monitorEventLoopDelay } = require('perf_hooks');
const h = monitorEventLoopDelay({ resolution: 10 });
h.enable();
setInterval(() => {
console.log({
mean: h.mean,
max: h.max,
min: h.min
});
}, 10000);
// 分片处理大数据
async function processLargeArray(array, chunkSize = 1000) {
const results = [];
for (let i = 0; i < array.length; i += chunkSize) {
const chunk = array.slice(i, i + chunkSize);
results.push(...chunk.map(item => processItem(item)));
// 让出事件循环
await new Promise(setImmediate);
}
return results;
}
// 使用worker_threads处理CPU密集任务
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
if (isMainThread) {
const worker = new Worker(__filename, { workerData: largeData });
worker.on('message', (result) => console.log(result));
} else {
const result = heavyComputation(workerData);
parentPort.postMessage(result);
}
HTTP优化
// HTTP/2服务器
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('Hello HTTP/2
');
});
// Keep-Alive连接
const http = require('http');
const agent = new http.Agent({
keepAlive: true,
maxSockets: 50,
maxFreeSockets: 10,
timeout: 60000
});
// 响应压缩
const zlib = require('zlib');
const { createGzip } = zlib;
function compressResponse(req, res, data) {
const acceptEncoding = req.headers['accept-encoding'] || '';
if (acceptEncoding.includes('gzip')) {
res.writeHead(200, { 'Content-Encoding': 'gzip' });
zlib.gzip(data, (_, result) => res.end(result));
} else {
res.end(data);
}
}
// 缓存策略
const etag = require('etag');
function serveWithCache(req, res, content) {
const e = etag(content);
if (req.headers['if-none-match'] === e) {
res.writeHead(304);
return res.end();
}
res.writeHead(200, {
'ETag': e,
'Cache-Control': 'public, max-age=3600'
});
res.end(content);
}
诊断工具
// 诊断报告
const { writeHeapSnapshot, getHeapStatistics } = require('v8');
const { generateHeapSnapshot } = require('node:vm');
// 生成报告
process.report.writeReport('./report.json');
// Clinic.js分析
// clinic doctor -- node app.js
// clinic flame -- node app.js
// clinic bubbleprof -- node app.js
// 0x火焰图
// 0x -o flamegraph.html app.js
// 内置分析器
// node --prof app.js
// node --prof-process isolate-*.log
最佳实践
- 使用最新LTS版本:获取性能改进
- 启用严格模式:帮助V8优化
- 避免同步操作:阻塞事件循环
- 使用连接池:复用数据库连接
- 合理使用缓存:减少重复计算
- 监控内存:及时发现泄漏
Node.js性能优化是一个持续过程,需要结合监控数据不断调整。
本文链接:https://www.kkkliao.cn/?id=756 转载需授权!
版权声明:本文由廖万里的博客发布,如需转载请注明出处。



手机流量卡
免费领卡
号卡合伙人
产品服务
关于本站
