这里讲的是如何利用Chrome浏览器来debug node程序,并利用Profiler来做性能分析。
Chorme Devtools不仅仅能做网页调试,还可以调试node程序,借助此工具,可以查看调用栈信息,燃尽图,内存快照等,辅助我们对程序进行优化。

使用步骤

下面是步骤

  1. 启动server

    1. node --inspect-brk index.js
  2. 打开chrome,输入chrome://inspect

image.png

  • node —inspect-brk index.js // 这个是暂停调试模式
  • 打开chrome,输入chrome://inspect
  • 继续执行代码后,点击Profile,然后开始生成快照
  1. ab工具进行压测,完了结束快照;

这样我们就能分析调用栈,燃尽图等;

实例:根据结果优化程序

默认Heavy(Bottom up)
image.png
选择Chart
image.png
这个结果显示 readFileSync占用了很大的性能,怀疑可能每一次请求都在调用readFileSync,那么考虑是不是要提取出来。

1. 优化这readFileSync

查看代码:

  1. app.use(
  2. mount('/', async (ctx) => {
  3. ctx.body = fs.readFileSync(__dirname + '/source/index.htm', 'utf-8')
  4. })
  5. );

这样写每一次请求之后都会去readFile,所以把它抽出来:

  1. const html = fs.readFileSync(__dirname + '/source/index.htm', 'utf-8')
  2. app.use(
  3. mount('/', async (ctx) => {
  4. ctx.body = html
  5. })
  6. );

在进行ab测试,修改之后qps已经提升到400多,以前是200多,翻了一倍。

2. 优化byteLengthUtf8

image.png
还是利用Chrom Dev tools,发现:

  • 之前的最大性能占比(readFileSync)已经不见了,优化成功;
  • 取而代之的新的占比最高是这个:byteLengthUtf8

思考:
为什么会有这个byteLengthUFT8(这个是获取UTF8的长度),这里有个“经验活儿”就是:
node接口里面的body 比如 ctx.body = stringBody这个stringBody是string的话,是要默认变成buffer的(底层是c++),所以这里涉及一个转换;
所以优化的思路就是直接用buffer来输出:

修改前:

  1. const html = fs.readFileSync(__dirname + '/source/index.htm', 'utf-8')

修改后:

  1. // 不指定utf8
  2. const htmlBuf = fs.readFileSync(__dirname + '/source/index.htm')
  3. app.use(
  4. mount('/', async (ctx) => {
  5. ctx.type = 'html' // buffer就需要指定是html了,否则可能就当成要下载的文件了
  6. ctx.status = 200
  7. ctx.body = htmlBuf
  8. })
  9. );

改完之后再来ab测试,效果:qps直接变成900多了,很大的提升!

程序性能优化的准则

  • 减少不必要的计算
  • 空间换时间

所谓“不必要的计算”,最重要的思考思考:在用户能感知到的时间里,这个计算是不是必要的?
image.png

  • 如果是不必要的,是不是可以提前将计算结果缓存
  • 比如上面例子中,把服务阶段的活儿安排到启动阶段;

    快照:检测内存泄漏

    类似上文中,利用chrome dev tools,思路就是内存快照:
    启动server进行ab测试。
    测试之前照一个快照, 测试之后再照一个快照。理论上没有内存泄漏的情况下,两次快照得到的内存占用大小应该差不多。但是如果发现有较大差别,说明存在内存泄漏!
    举个例子:
    伪造一个内存泄漏:
    1. const leak = []
    2. app.use(
    3. mount('/', async (ctx) => {
    4. ctx.body = html
    5. leak.push(html)
    6. })
    7. );

对比前后快照,可以看到,压测前后内存差了很多:
image.png
可以看到:

  • 启动ab测试前,快照内存623MB
  • 结束ab测试之后,快照内存1728MB

典型的内存侧漏了~

dev tool 可以选择「对比」能很清晰的看到,下图所示,分配了多少内存,释放了多少内存:
image.png
上图显示,分配了1159 169….释放了468 856….
image.png
点击一个string可以在下面看到,这个内存的持有者就是leak变量,就是刚才伪造的内存泄漏数组。