NodeJS 性能优化之 CPU 看图篇

服务稳定性到一定程度之后,都会开始经历一段精细化运营的过程,从成本意识角度来说也是成立的。作为前端出身的NodeJS开发者们,产生共鸣的那就是如何能够直观且快速发现性能瓶颈,能够像调试前端的JS代码那样可视化,堆栈化,接下来我们就针对常见的CPU性能分析方法来揭开NodeJS的CPU面纱。

一、CPU使用情况可视化展示(火焰图—Flame Graph)

充分利用劳动工具有助于帮助我们提升定位问题的效率,Linux kernal自带的系统性能分析工具perf,为我们提供函数级与指令级的热点查找,常用于性能瓶颈的查找与热点代码定位。

#NodeJS如何正确完整的采集火焰图呢?

1-1、用例构造

NodeJS服务代码示例—JSON编解码,如下片段:

1-2 启动方式:

启动参数:--perf_basic_prof或—perf-basic-prof适用于node@0.11.13

也可以使用--perf_basic_prof_only_functions

标准方式:node --perf_basic_prof JsonParse.js

MIG tafNodeJS启动方式:私有模板配置启动参数,如下:


<taf>

<application>

    <server>

        node-args=--perf-basic-prof

</server>

</application>

</taf>

注:--perf_basic_prof或--perf-basic-prof会对应生成一个/tmp/perf-pid.map文件,如图:

1-3 perf脚本采集函数和热点代码

#查看NodeJS服务进程pid,采集时需要用到。命令:$ ps –ef | grep ‘worker’

#采集脚本:$ perf record -F 99 -p 182497 -g -- sleep 60

参数说明如下:

采集频率(ms)

进程pid

调用记录

记录时长

-F 99

-p 182497

-g

--sleep 60

#进程对应的符号表perf-pid.map权限设置:$chown root /tmp/perf-pid.map

踩过的坑!!!是为了消除下面这个问题的

File /tmp/perf-PID.map not owned by current user or root, ignoring it (use -f to override).

Failed to open /tmp/perf-PID.map, continuing without symbols

  • 挖出FlameGraph开源库里面的stackcollapse-perf.pl和flamegraph.pl

http://github.com/brendangregg/FlameGraph

  • svg文件生成

单一颜色:$ perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > xxx.svg

多种颜色:perf script | ./stackcollapse-perf.pl | ./flamegraph.pl --color=js –hash > xxx.svg,如下图:

二、CPU火焰图的理解与性能分析

2.1 通过上面的步骤采集出两种不同颜色系的火焰图,如下图

2.2 火焰图颜色对应关系,如下表:

颜色

类型

绿色

JS代码调用

蓝色

优化编译代码

黄色

C++/C代码

红色

libuv系统调用

2.3 火焰图形状对应关系

形状

含义

每一个平面方块

一个函数在栈中的位置(也称一个栈帧)

Y轴

栈的深度(也叫栈的帧数)

X轴

表示总的样例,不过它们左右顺序没有特殊含义

每个平面方块的宽度

方块的宽度标示CPU使用时间或者说相对父函数而言使用CPU的比率,越宽代表占用CPU的时间越长,或者使用CPU很频繁

2.4 JSON序列化与反序列化火焰图分析

采用ab进行压力测试分析JSON.parse与JSON.stringify性能开销

压测命令:ab –n 3000000 -c 50 http://ip:port/jsonParse

从火焰图看到JsonParse.js里面耗时主要消耗在JSON序列化和反序列化

几个常见的栈帧类型说明:

栈帧

含义

LazyCompile

指的是下回会被编译

Builtin

指的是C++内置的运算方法

Stub

C入口桩代码:作用是在js的JIT代码中,如果要调用Runtime的函数,则通过CEntryStub实现

V8::internal

内部命名空间,就是C++的namespace,在V8的源代码可以找到对应的namespace

2.5 JSON反序列化(JSON.parse)源码分析

概念普及——解析器常见原理:

a) 词法分析

b) 语法分析生成抽象语法树(AST)

c) 针对抽象语法树进行语义分析,构建你需要的内部数据结构或生成代码

通过局部查看火焰图分析源码

1 Stub:CEntryStub:C入口桩代码,在JS的JIT代码中,提供调用Runtime的函数(如DOM函数或者JS的builtin函数)

2【编译builtins.h】v8::internal::Builtin_JsonParse

3【解析器json-parser.cc】v8::internal::JsonParser<true>::ParseJson

4【词法分析json-parser.cc】v8::internal::JsonParser<true>::ParseJsonValue

5【语法分析json-parser.cc】v8::internal::JsonParser<true>::ParseJsonObject

小结:通过火焰图我们能够清晰的看到函数的调用栈,并能够找到哪些函数是耗时较多的

JSON序列化流程相似相似,感兴趣的同学可以看一下V8的json-stringifier.cc和对应的.h文件

三、CPU性能分析的另一种可视化dot图

3.1 需要gprof2dot脚本

工程地址:https://github.com/jrfonseca/gprof2dot.git

3.2 基于perf.data文件转换成dot文件

$ perf script -i perf.data.pid | python gprof2dot.py –f perf –e 1 –o xxx.dot

3.3 基于perf.data文件转换成dot文件

$ dot –Tsvg xxx.dot –o xxx.svg

在linux物理机的尝试:

下载到PC磁盘,打开即可:

附录

https://zhuanlan.zhihu.com/p/27147421

https://www.zhihu.com/question/24640264

http://blog.12.rs/notes/V8-0.2.5-JIT/

https://github.com/zfengzhen/Blog/blob/master/article/hold%E4%BD%8F%E4%BD%A0%E7%9A%84%E5%90%8E%E5%8F%B0%E7%A8%8B%E5%BA%8F.md

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

郑清江的专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Micro_awake web

VSCode配置eslint

在Vue.js项目中,使用的是eslint检查。 而在我写完代码后,cnpm run dev运行命令。。。然后悲剧了,一大堆报错!╮(╯▽╰)╭ 安装插件:Ve...

1.5K5
来自专栏申龙斌的程序人生

零基础学编程016:Python IDLE的代码编辑器

Python IDLE是Python的集成开发和学习环境,而WinPython集成更多的开发工具包,比如在《零基础学编程012:画出复利曲线图》提到的numpy...

2835
来自专栏华章科技

这件神器,每个 Python 学习者都值得一试

Jupyter Notebook 是一款 Web 应用,它能让用户将上面说的各种窗口里的东西,全部组合到一个可读性好,易于共享,且对新手友好的文档中。这个文档里...

722
来自专栏python小白到大牛

这件神器,每个 Python 学习者都值得一试

不论你是刚开始学 Python,还是正在啃数据分析的骨头,对你来说,不断在各种命令行窗口和编辑器里切来切去,或者不断打开各种窗口查看 matplotlib 的输...

1174
来自专栏前端知识分享

深入理解Vue的生命周期

  谈到Vue的生命周期,相信许多人并不陌生。但大部分人和我一样,只是听过而已,具体用在哪,怎么用,却不知道。我在学习vue一个多礼拜后,感觉现在还停留在初级阶...

1033
来自专栏高性能服务器开发

libevent源码深度剖析七 事件主循环

(1)libevent源码深度剖析一 序 (2)libevent源码深度剖析二 Reactor模式 (3)libevent源码深度剖析三 libevent基...

1044
来自专栏Kubernetes

Kubernetes Deployment滚动更新场景分析

基于Kubernetes v1.7.4 关于Kubernetes Deployment滚动更新 Kubernetes官网文档说明:https://kube...

3709
来自专栏24K纯开源

Android Studio快捷键每日一练(1)

1、高亮显示相同的字符串 苹果:Cmd+shift+F7    Windows:Ctrl+shift+F7 这个快捷键会在当前文件中搜索这个字符串出现的所有位置...

2025
来自专栏林德熙的博客

C# 从零开始写 SharpDx 应用 初始化dx修改颜色

本文来告诉大家如何在上一篇博客创建的窗口里面使用 Sharpdx 初始化,然后设置窗口颜色。

1491
来自专栏Django中文社区

已知小问题修正

在模型中指定排序 为了让文章(Post)按发布时间逆序排列,即最新发表的文章排在文章列表的最前面,我们对返回的文章列表进行了排序,即各个视图函数中都有类似于 P...

3014

扫码关注云+社区