JavaScript 代码性能分析:寻找瓶颈
\n\n当您的 Node.js 项目开始变慢时,第一反应可能是“我需要用 Rust 重写所有代码”。但别着急!大多数情况下,问题出在少数几行效率低下的代码上。在本文中,我们将详细讲解如何使用简单的性能分析工具来找到这些“瓶颈”。您将学习如何测量性能、构建火焰图,以及了解 CPU 时间都花在了哪里。
\n\n为什么要分析代码?
\n\n假设您的服务器每秒处理 100 个请求,但您需要它处理 500 个。您可以优化所有内容,但这需要数周时间。或者,您可以找到一个占用 80% 时间的函数,并在一个小时内修复它。性能分析恰恰能向您展示时间被花费在哪里。
\n\n让我们考虑一下需要进行性能分析的主要场景:
\n- \n
- API 响应延迟高 \n
- 内存泄漏 \n
- 无明显原因的 CPU 高负载 \n
- 处理大型数据数组速度缓慢 \n
工具 1:内置的 Node.js 性能分析器 (--prof)
\n\n最简单的方法是使用 --prof 标志运行 Node.js。它会收集执行统计信息,并将其保存到名为 isolate-*.log 的文件中。
让我们创建一个包含瓶颈的测试脚本:
\n\n// slow.js\nfunction heavyComputation() {\n let sum = 0;\n for (let i = 0; i < 1e7; i++) {\n sum += Math.sqrt(i) * Math.sin(i);\n }\n return sum;\n}\n\nfunction fastFunction() {\n return 42;\n}\n\nconsole.time('total');\nheavyComputation();\nfastFunction();\nconsole.timeEnd('total');\n\n\n运行性能分析:
\nnode --prof slow.js\n\n执行后,会生成一个名为 isolate-0x...-v8.log 的文件。要读取它,请使用 node --prof-process 工具:
node --prof-process isolate-0x...-v8.log > profile.txt\n\n打开 profile.txt,您会看到一个包含时间百分比表格:
[Summary]:\n ticks total nonlib name\n 785 78.5% 85.3% JavaScript\n 215 21.5% 14.7% C++\n ...\n[Bottom up (heavy) profile]:\n ticks parent name\n 500 50.0% LazyCompile: *heavyComputation slow.js:2:17\n 100 10.0% Builtin: MathSqrt\n 50 5.0% Builtin: MathSin\n\n\n我们可以看到 50% 的时间都花费在 heavyComputation 函数上。现在我们知道应该优先优化什么了。
工具 2:Chrome DevTools (检查器)
\n\n为了进行更直观的分析,让我们连接 Chrome DevTools。使用 --inspect 标志运行 Node.js:
node --inspect slow.js\n\n打开 Chrome 并访问 chrome://inspect。点击“打开用于 Node 的专用 DevTools”。转到“分析器 (Profiler)”选项卡 → “开始 (Start)” → 运行脚本 → “停止 (Stop)”。
您将看到一个火焰图——一种图表,其中块的宽度表示执行时间。块越宽,函数就越“热”。我们的 heavyComputation 将是一个巨大的矩形。
提示: 使用某个函数上的“聚焦选定项 (Focus selected)”过滤器来查看其内部调用。例如,您可能会注意到 Math.sqrt 被调用了 1000 万次——也许预先计算平方根是值得的。
工具 3:perf_hooks — 代码中的精确测量
\n\n有时您需要测量特定代码段,而无需运行外部工具。为此,请使用内置的 perf_hooks 模块。
测量函数执行时间的示例:
\n\nconst { performance } = require('perf_hooks');\n\nfunction processData(items) {\n let result = [];\n for (let item of items) {\n // Simulating complex processing\n for (let j = 0; j < 1000; j++) {\n result.push(item * j);\n }