记一次Node项目的优化

这两天针对一个Node项目进行了一波代码层面的优化,从响应时间上看,是一次很显著的提升。
一个纯粹给客户端提供接口的服务,没有涉及到页面渲染相关。

背景

首先这个项目是一个几年前的项目了,期间一直在新增需求,导致代码逻辑变得也比较复杂,接口响应时长也在跟着上涨。
之前有过一次针对服务器环境方面的优化(node版本升级),确实性能提升不少,但是本着“青春在于作死”的理念,这次就从代码层面再进行一次优化。

相关环境

由于是一个几年前的项目,所以使用的是Express+co这样的。
因为早年Node.js版本为4.x,遂异步处理使用的是yield+generator这种方式进行的。
确实相对于一些更早的async.waterfall来说,代码可读性已经很高了。

关于数据存储方面,因为是一些实时性要求很高的数据,所以数据均来自Redis。
Node.js版本由于前段时间的升级,现在为8.11.1,这让我们可以合理的使用一些新的语法来简化代码。

因为访问量一直在上涨,一些早年没有什么问题的代码在请求达到一定量级以后也会成为拖慢程序的原因之一,这次优化主要也是为了填这部分坑。

一些小提示

本次优化笔记,并不会有什么profile文件的展示。
我这次做优化也没有依赖于性能分析,只是简单的添加了接口的响应时长,汇总后进行对比得到的结果。(异步的写文件appendFile了开始结束的时间戳)
依据profile的优化可能会作为三期来进行。
profile主要会用于查找内存泄漏、函数调用堆栈内存大小之类的问题,所以本次优化没有考虑profile的使用
而且我个人觉得贴那么几张内存快照没有任何意义(在本次优化中),不如拿出些实际的优化前后代码对比来得实在。

几个优化的地方

这里列出了在本次优化中涉及到的地方:

一些不太合理的数据结构(用的姿势有问题)

串行的异步代码(类似callback地狱那种格式的)

数据结构相关的优化

这里说的结构都是与Redis相关的,基本上是指部分数据过滤的实现
过滤相关的主要体现在一些列表数据接口中,因为要根据业务逻辑进行一些过滤之类的操作:

过滤的参考来自于另一份生成好的数据集

过滤的参考来自于Redis

其实第一种数据也是通过Redis生成的。:)

过滤来自另一份数据源的优化

就像第一种情况,在代码中可能是类似这样的:

let data1 = getData1() // [{id: XXX, name: XXX}, ...] let data2 = getData2() // [{id: XXX, name: XXX}, ...] data2 = data2.filter(item => { for (let target of data1) { if (target.id === item.id) { return false } } return true })

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsszss.html