$ sudo perf record -F 99 -p 28671 -g -- sleep 30
$ sudo chown root /tmp/perf-28671.map
$ sudo perf script > perf.stacks
$ ./stackcollapse-perf.pl --kernel < perf.stacks | ./flamegraph.pl --color=js --hash > flamegrap1.svg
perf record 会将记录的信息保存到当前执行目录的 perf.data 文件,使用 perf script 读取 perf.data 的 trace 信息写入 perf.stacks, 然后通过FlameGraph 绘制火焰图。
—color=js 指定生成针对 js 配色的 svg,即:
green:JavaScript。 blue:Builtin。 yellow:C++。 red:System(native user-level, and kernel)。
ab 压测用了 30s 左右,浏览器打开 flamegraph.svg,截取关键的部分如下图所示:
从上图可以看出:最上面的绿色小块(即 JavaScript 代码)指向 test/app.js 第 18 行,即 GET /auth
这个路由。再往上看,黄色的小块(即 C++ 代码) node::crypto::PBKDF2 占用了大量的 CPU 时间。
解决方法:将同步改为异步,即将 crypto.pbkdf2Sync 改为 crypto.pbkdf2,修改如下:
const crypto = require('crypto')
const Paloma = require('paloma')
const app = new Paloma() const users = {}
app.route({
method: 'GET',
path: '/newUser',
controller(ctx) {
const username = ctx.query.username || 'test'
const password = ctx.query.password || 'test'
const salt = crypto.randomBytes(128).toString('base64')
const hash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex')
users[username] = {
salt,
ctx.status = 204
app.route({
method: 'GET',
path: '/auth',
async controller(ctx) {
const username = ctx.query.username || 'test'const password = ctx.query.password || 'test'
if (!users[username]) {
throw (400)
const hash = await new Promise((resolve, reject) = >{
crypto.pbkdf2(password, users[username].salt, 10000, 64, 'sha512', (err, derivedKey) = >{
if (err) {
return reject(err)
resolve(derivedKey.toString('hex'))
}) if (users[username].hash === hash) {
ctx.status = 204
} else {
throw (403)
app.listen(3000)
复制代码
- 818
-
嘿嘿不务正业
Visual Studio Code
Node.js
- 100
-
tangdou369098655
Node.js
- 550
-
upward_growth
Node.js
- 785
-
zxg_神说要有光
Docker
Node.js