上次讲到作为一个独立存在的node进程,我们在做故障排查的时候应该注意一个是内存还有一个就是cpu。上次讲完了通过heapsnapshot文件分析内存占用过高的某一时刻,进程中哪个对象占用内存较大来找出内存泄露的原因。那么本次来讲如何分析cpu耗时较长的函数来找出性能瓶颈。
同样本次所使用的代码demo还是只是用一个占用cpu比较高的函数来充当真实场景中的造成cpu资源浪费的函数,真实的场景可能会更加复杂。demo主要是实现了一个http服务器,在每次访问服务器时,求一次斐波那契数列。比较特殊的是用到了v8-profiler-node8这个第三方模块来输出记录一段时间内cpu时间分配的cpu profile文件,用到了process模块来实现进程间传递信号事件。
const http = require("http");
const profiler = require('v8-profiler-node8');
const fs = require('fs');
const process = require('process');
var profilerRunning = false
function toggleProfiling () {
if (profilerRunning) {
const profile = profiler.stopProfiling()
console.log('stopped profiling')
profile.export()
.pipe(fs.createWriteStream('./myapp-'+Date.now()+'.cpuprofile'))
.once('error', profiler.deleteAllProfiles)
.once('finish', profiler.deleteAllProfiles)
profilerRunning = false
return
}
profiler.startProfiling()
profilerRunning = true
console.log('started profiling')
}
toggleProfiling();
process.on('SIGTERM', ()=> { toggleProfiling()})
http.createServer(function(req,res){
res.writeHead(200,{"Content-type":"text/blain"});
res.write("Hello NodeJs"+fib(35));
res.end();
}).listen(8889);
function fib (n) {
var result=0;
if(n>2){
result=fib(n-1)+fib(n-2)
}else if(n>0){
result=1;
}
return result;
}
进程刚执行的时候,会通过profiler模块的startProfiling api来开始记录cpu时间分配,之后通过ab测试的命令来访问服务端,通过进程监视器监控cpu占用率稳定在将近100%时,通过kill命令来终止进程。kill命令默认传递的就是'SIGTERM'事件,所以当kill向这个node进程传递事件时,就会执行stopProfiling api来自动输出一份cpu profile文件。
把node进程启动以后,需要以后通过ab压测来给访问进程:
ab -t 300 -c 10 http://localhost:8889/
kill掉进程后,当前目录下就会出现一个cpuprofile文件,我们如何来分析呢?还是通过chrome浏览器来进行分析。点击开发者工具右侧的点->more tools->JavaScript Profiler就可以调出分析cpu profile文件的主页面,点击load导入profile文件。
通过chart选项可以看到cpu时间分配的火焰图,和我们之前讲解javascript事件循环时分析的调用图很相近,在图中可以明显看出来,在空闲了4秒以后,服务端开始接收请求,请求期间进程最终调用的fib函数占用了cpu的绝大部分工作时间。
可以把分析图形切换到Heavy模式,按照self time倒叙排列,就能看到占用cpu时间较多的函数,而这种函数是很有可能成为进程cpu过高的瓶颈的。图中我们可以明显地看出来,占用时间最多的就是fib函数。
其实除了本次讲解的cpu占用时间过长的瓶颈以外,我们还需要关注的是进程是否进入了无限循环的同步函数中导致cpu长时间飙到100%,进而变成无法执行事件循环和接收请求的假死状态。还有未被正常捕获的异常导致进程崩溃。介于本次的内容较为基础,所以还是先讲寻找cpu耗时瓶颈这个问题。
如果您对本文感兴趣想关注更多技术文章,请关注作者公众号,更多好文章为您呈现~