You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
luog@luog-X510UQR:~/p/TEB/frameworks/Java/act$ mvn -q -P eclipselink_mysql clean package
luog@luog-X510UQR:~/p/TEB/frameworks/Java/act$ cd target/dist
luog@luog-X510UQR:~/p/TEB/frameworks/Java/act/target/dist$ unzip actframework-1.8.1-r88180d.zip
luog@luog-X510UQR:~/p/TEB/frameworks/Java/act/target/dist$ ./run -p eclipselink_mysql
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128M; support was removed in 8.0
_ ___ _ _ _ _ _
/\ / | |_ |_) /\ |\/| |_ \ / / \ |_) |/
/--\ \_ | | | \ /--\ | | |_ \/\/ \_/ | \ |\
powered by ActFramework r1.8.1-6fcc0
version: r1.8.1-88180d
scan pkg: com.techempower.act
base dir: /home/luog/p/TEB/frameworks/Java/act/target/dist
pid: 25323
profile: eclipselink_mysql
mode: PROD
zen: There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
1. 案情回顾
老码农在 一场版本升级引发的性能血案的追凶过程 中谈到了 ActFramework 在 TFB 第 N 轮内部测试中全线溃败落入 Spring 朋友圈的不堪回首之往事. 历经三天两夜追凶过程, 老码农终于定位到了一
ActContextBase.<init>
中以 500K 字节初始化S.Buffer
为首的犯罪集团, 并提交了新的 PR, 最新的内部测试结果已经收到果然让 Act .................................................... 某些部分重回性能巅峰. 还是上图先:1.1 JSON 测试结果比较
TFB JSON - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682261-a9e44bbe-63ce-11e8-8990-48ccfa94e7f7.png)
TFB JSON - act-1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40682303-bf70e9e2-63ce-11e8-908d-aa44f9ed6c83.png)
1.2 单次查询测试结果比较
TFB Single Query - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682456-2021199c-63cf-11e8-9fbd-77891c6e3584.png)
TFB Single Query - act-1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40682483-354b4b80-63cf-11e8-8da9-d5007ffe5730.png)
1.3 多次查询测试结果比较
TFB Multiple Queries - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682571-73e713a6-63cf-11e8-9990-c685b7e56d11.png)
TFB Multiple Queries - act-1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40682595-82654b64-63cf-11e8-952b-5df0235cb39c.png)
1.4 数据 + 后台模板测试结果比较
TFB Fortunes - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682653-ba0c2588-63cf-11e8-9efb-fabf76f3b3f5.png)
TFB Fortunes - act-1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40682682-cd564bc8-63cf-11e8-9247-0ac9656240e2.png)
1.5 多次数据更新测试结果比较
TFB Updates - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682799-0244e92a-63d0-11e8-8c34-448802b2a023.png)
TFB Updates - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682883-3fb79884-63d0-11e8-94de-625cd2720c58.png)
1.6 静态字串返回测试结果比较
TFB Plaintext - act-1.8.2
![image](https://user-images.githubusercontent.com/216930/40682942-629701d2-63d0-11e8-9bef-93aae9100cfb.png)
TFB Plaintext - act-1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40682961-74689f06-63d0-11e8-95f6-9c0c2e6e062a.png)
数据不会说谎, 可以看出老码农的努力让 ActFramework 在 JSON/Plaintext 两项测试中重回性能王座. 但是 SQL 数据库的各项测试还是全线溃败, 这有点令老码农干瞪眼儿了. 不过老码农是那种轻言放弃的人么. 啥也不说了, 挽起袖子开始撸吧.
2. 数据历险
从上次的教训中我们已经知道了 JProfiler 是一个更好的性能检测工具. 所以我们还是继续依赖 JProfiler 为我们提供分析数据.
2.1 获得历史对照数据
先找出最近一次没有性能降级问题的 SNAPSHOT, 感谢 TechEmpower 为我们提供的 tfb-status 报告, 我们很容易找到最近一次没有出现问题的版本为
88180d6d3e3aded7682c653f3f7766b578b16835
. 运行下面的命令检出该版本:ActFramework 为 TFB 数据访问测试提供了多项组合, 包括:
这些组合的测试成绩同步下降, 有充分理由相信他们都是有相似的原因引起的. 老码农选择了 eclipselink + mysql 组合来分析性能下降的原因, 主要原因是 eclipselink 是标准的 JPA 实现, 而且比 hibernate 要简单一下(只是比 hibernate 简单一点点, 后来的经历让老码农充分了解了数据库访问的复杂程度).
下面我们就按照该组合来 build 运行版本, 并启动应用:
下面就先用 wrk 生成两次 15s 的压测请求, 预热 JVM
接下来就是启动 JProfiler 连接刚刚启动的进程:
JProfiler 在启动的时候会询问是否 instrument 还是 sample. 这里我们选择 instrument, 因为需要监测的部分我们是很清楚的
需要注意的是 Filter 的定义对于 instrument 非常重要. 我们在这里选择对这个测试更加重要的类, 简单地说就是和数据库访问相关的类:
在上面的对话框中我们选择了一下 package:
一共有超过 4000 个类, 其中绝大部分都是 eclipselink 的.
同时我们也打开数据库 probe 设置:
JProfiler 开始之后运行 wrk 来生成压测请求 30 秒:
下面就是 JProfiler 捕获到的数据:
我们先保存为 SNAPSHOT, 等收集到有问题版本的数据之后对二者做对比.
2.2 获得最新数据
还是通过 tfb-status 拿到最近的版本, checkout 出来运行:
按照先前的方式先压测两次 15s 预热 JVM:
JProfiler 也是按照先前的方式连接上面的进程, 开始监测. 同时跑 wrk 生成压测请求 30 秒, 结果如下:
下面对两次测试的 CPU Hot Spots 做比较:
1.8.1 (Good one)
![image](https://user-images.githubusercontent.com/216930/40693337-3841604c-63fa-11e8-8d79-a2e543d700b0.png)
1.8.8-RC6 (Bad one)
![image](https://user-images.githubusercontent.com/216930/40693372-64adc6ca-63fa-11e8-91d7-ca3e5c8bf432.png)
看不出什么东西, 对吧. 看不出就对了, 因为老码农也是一脸懵比. 不过发现一个现象, 两个 Session 都有很多方法, invocation 次数超级多, 但是 self 时间非常短:
也许把这些方法过滤掉会有一些发现. 说干就干, 重新起一个 JProfiler Session, 把上面那些方法都加到 Session Setting 的 Ignore Methods 当中:
![image](https://user-images.githubusercontent.com/216930/40694137-6ee119e0-63fe-11e8-9b14-b6985cb75aa3.png)
搞定这些设置之后从头再撸一遍, 情况是这样的:
1.8.1
![image](https://user-images.githubusercontent.com/216930/40694132-689a11ea-63fe-11e8-8475-c4cdf7b3d77e.png)
1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40694106-4c540252-63fe-11e8-833e-8ffe7a4e3593.png)
还是不清楚为啥 RC6 比 1.8.1 速度降低了很多, 也许是老码农的 8550U 的机器不够强劲, 反映不出问题吧. 不过还是让老码农逮到一个比较有趣的地方, 两个 session 都有超过 20K 的
com.mysql.jdbc.connectionImpl.prepareStatement
的调用. 这个让老码农很奇怪,PreparedStatement
不应该是重复利用吗?老码农决定试试 JProfiler 的 Sampling 方式, 又重头开始撸 (这种撸法简直是要人命的节奏啊). 最后得出的情况是:
1.8.1
![image](https://user-images.githubusercontent.com/216930/40694424-cc7c7986-63ff-11e8-9668-b5184e9a4155.png)
1.8.8-RC6
![image](https://user-images.githubusercontent.com/216930/40694499-2a5867c2-6400-11e8-9fb4-f309246652a3.png)
貌似更加清晰一点, 但依然看不出性能下降的原因. 但还是有收获的, 这个 readonly 的请求怎么会在有 ConnectionImpl.rollback 的情况. 结合上次发现的 prepareStatement 调用, 不需要问元芳, 老码农就能断定此中必有蹊跷. 本来以为可以停歇了, 没想到采坑的旅程才刚刚开始. 为了不耽搁大家阅读时间, 就直接看结局吧
3. 结局
老码农第一个深入研究的问题: 为啥 Connection 会 rollback, 这与 prepareStatement 不停调用有何关联, 结果是给 Eclipselink 项目提了一个 Issue 报告, 具体内容也是 TLDR, 欲知详情, 移步这里: eclipse-ee4j/eclipselink#107
那 rollback 的问题来自于 act db 总是建立事务, 对于只读的请求最后调用事务的 rollback, 这个额外开销不能接受, 经过三天两夜连续撸? (噢, 说错了, 是撸码), act 现在可以在数据源配置上只读数据源了, 对于 TFB 项目, 现在的配置是这样的:
看到其中的
db.slave
了吗? 那就是为只读操作准备的, 只读数据源没有特殊设定的都继承主数据源设定. 看官一定会问, 怎么才能知道应该使用只读而不是主数据源, 这个问题的答案是分两种情况:这次的数据历险触发整个 act-sql-common 包括 ebean 和 JPA 的价格完全重写, 而且让老码农采坑无数, 差点就精尽人亡, 不过结果 .................................... 结果老码农也不知道啊, 已经升级了 TFB 项目, 提交了 PR, 需要再等差不多 100 个小时之后就能见分晓了, 希望能给有个惊喜.
咱们下回分解
The text was updated successfully, but these errors were encountered: