记一次性能分析

公司首页有个展示列表的接口,我也曾参与过其中部分方法的编写,反应时间很慢大约有3-4s,因为无从下手优化,请教D哥,D哥将代码重写将代码的运行时间减少到了0.6s左右,但是D哥也说不清原来代码为什么这么慢,于是我就对原来的代码和改进的代码进行了粗略分析。

在分析代码运行时间的工具上,看了网上各种各样的性能分析的工具,也试用了JProfiler,但是感觉过于底层分析,不是我想要的,选择了Spring提供的StopWatch类来进行断点记录对应时间,简单粗暴,符合我的需求。

原来的接口,平均耗时3.7s,大致步骤抽象如下。

1. 新建集合,查询出A

2. 新建集合,查询出B

3. 新建集合,查询出C

3. 新建集合,进行一个封装的多查询(D)

4. 排序

5. 新建集合,过滤筛选(E)

6. 手动分页得到F

使用Stopwatch后分析报告如下

ms    %  taskName

00005 000% 开始执行方法

00259 007% 查询A

00072 002% 查询B

00001 000% 查询C

02755 073% 封装多查询 D

00000 000% 排序

00705 019% 过滤  E  (for循环调用数据库并做筛选)

00000 000% 手动分页得到F

这里我们看到D步骤和E步骤占用了92%的时间,问题就出现在这两个步骤上,而D很明显是大头.

于是对D内部再进行分析

ms    %  taskName

00118 005% D1

02427 093% D2 (for循环里调数据库查询486次  486*0.005 =2.43s)

00059 002% D3

00000 000% D4

所以主要问题就出现在D2和E上面

下面我们再对新接口做分析,大致步骤如下 (与上面的ABCDEF并不完全一样)

1. 新建集合 A

2. 筛选 B in (A)

2. 筛选 C in (B)

3. 集合 D in (B,C)

4. 分页,由D得到E,进行封装多查询,得到F

综上

原始接口进行各种筛选和处理后,最后分页.

新接口先获得筛选后的集合,然后再分页查询(10条),再处理,少了几百次调数据库。.

优化分析

1. 原始的逻辑总体上属于按顺序进行,a-b-c,每次数据会筛选减少,所以没法分页.

而改进的则是倒过来先获得条件b,c 然后a in (b,c),这样可以就可以进行分页,减少数据处理量.

2. 原始接口的大约80%时间用于for循环调用数据库进行判断.

而在改进中, 对于20%(E步骤)的优化,是一次查询先取出所有符合条件的对象集合b,作为后面的判断条件,使得a in(b)

对于60%(D2步骤)的优化,则是先进行了分页,使得数据量从486条变为10条,再进行for循环调用数据库就不会占用太多时间了。

其他可能的优化点

1.流的使用

发布了41 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/ScanQ/article/details/102808245