当前位置: 首页 > 后端技术 > Node.js

性能优化——让nodejs更快

时间:2023-04-04 00:23:18 Node.js

本文首发于北斗同构github。如需转载,请注明出处。前言很多前端工程师在页面性能调优的过程中很少关注代码本身的执行效率,更多关注网络消耗,比如资源整合减少请求数,压缩减少资源大小,缓存,等等,我觉得这不无道理。相反,它在很大程度上是正确的。比如JS本身的执行时间是30ms(毫秒)。五秒的页面加载时间比例太低。即使性能提升10倍,执行时间减少到3ms,整体性能提升也微乎其微,用户甚至察觉不到。因此,优化其他性能消耗大量金钱是比较明智??的。但是从Node.js(服务器端)的角度来看,JS本身的执行时间就变得非常重要了。在前面的例子中,如果执行时间从30ms减少到3ms,理论上QPS会提升10倍。也就是说,以前10台服务器承载的流量,现在1台服务器就可以承载,而且响应时间更短。那么如何优化Node端的性能呢?有两种方法,一种是通过Node/V8内置的profile能力,另一种是通过alinode的CPUprofile功能。前者只列出了各个函数的执行比例,后者包含了更完整的调用栈,可读性更强,也更容易定位问题,推荐后者。方法一:Node自带profile步骤一:使用--prof参数启动Node应用$node--profindex.js步骤二:通过测试工具loadtest给服务加压$loadtesthttp://127.0.0.1:6001--rps10第3步:处理生成的日志文件$node--prof-processisolate-0XXXXXXXXXXX-v8-XXXX.log>profile。txt第4步:分析profile.txt文件。profile.txt文件如下图,包括JS和C++代码消耗了多少tick。具体分析方法见节点简介文档。方法二:alinode的CPUprofile第一步:安装alinodealinode和Node社区版完全兼容的二进制运行环境,推荐使用tnvm工具安装$wget-O-https://raw.githubusercontent.com/aliyun-node/tnvm/master/install.sh|bash安装完成后,需要添加tnvm作为命令行程序。根据平台的不同,可能是~/.bashrc、~/.profile或~/.zshrc等。$source~/.zshrc是基于alinode-v3.8.0的,比如对应node-v8.9.0,下载此版本并启用它$tnvminstallalinode-v3.8.0$tnvmusealinode-v3.8.0步骤2:使用安装的alinode运行应用程序$node--perf-basic-prof-only-functionsindex.js步骤3:通过压测工具loadtest给服务加压$loadtesthttp://127.0.0.1:6001--rps10第四步:cpuprofile假设启动的worker进程号为6989,执行如下脚本,一个cpuprofile文件/tmp/cpu-profile-6989-XXX.cpuprofile脚本会在三分钟后生成在/tmp/目录下将cpuprofile文件导入Chrome开发者工具进行分析。下面以一个真实的案例来一步一步的展示如何做性能调优。通过1000次loadtest请求,计算平均RT,初始RT为15.8ms,不包括程序和GC消耗,性能消耗前三位分别是get,J和_eval。展开最耗性能的get方法调用栈,可以定位到get方法的位置。具体代码如下{key:'get',value:functionget(propName){if(!this.state[propName]){returnnull;}返回JSON.parse(JSON.stringify(this.state[propName]));}}在方法体中,JSON.parse(JSON.stringify(obj))虽然使用起来方便,但属于CPU密集型操作。做个验证,去掉这个操作,直接返回this.state[propName]。RT时间它已减少到12.3毫秒。这只是一个实验,不能直接去掉JSON.parse(JSON.stringify(obj)),否则会影响业务逻辑。参考常用拷贝方式的性能对比,配置自己的梯子。截图如下:性能最好的是lodashdeepclone,换成这个库,再次验证,RT降低到12.8ms。第二个表现是J方法,大部分是各个组件的render时间,暂时略过,同样对_eval方法优化了一次,RT降低到10.1ms。以此类推,根据CPUprofile找出性能消耗点,逐一优化。