原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。
在很久很久之前,有两篇关于JMH的文章。如果你做过性能优化,对于它自然是再熟悉不过。
ObjectMapper,别再像个二货一样一直new了! 顶级Java才懂的,基准测试JMH!
JMH屏蔽了一些环境的差异,可以让狗子们快速的获取吞吐量、平均响应时间等关键性指标。但是,性能的评测标准并不仅仅是单个维度。
比起那些了不起的性能,服务响应的稳定性,可能是另外一个比较重要的话题。
百分位
有时候,我们某些重要的服务,对每个请求的延迟忍受度都很低。如果我们用比较专业的词来描述的话,那就是:我们无法忍受任何长尾请求,即使平均响应时间非常的短。
这就需要一种指标来测量这种情况。为了解决这个问题,一个比较常用的指标,就是百分位数
(Percentile)。
如果非要找出一种形状的话,那它就是请求分布的直方图。
百分位可以这么理解。如果我们圈定一个时间范围,把每次请求
的耗时加入到一个列表中,然后,按照从小到大的顺序将这些时间进行排序。这样,我们取出某个位置请求的耗时,这个数字 就是TP值。可以看到,TP值(Top Percentile)和中位数、平均数等是类似的,都是一个统计学里的术语。
它的意义是,超过N%
的请求,都在X
时间内返回。比如TP90=50ms
,意思就是超过90th
的请求,都在50ms内返回。
这个指标能够反映出应用接口的整体响应情况。比如,某段时间发生了长时间的GC,就会影响高百分位的请求耗时增加。
我们一般分为Tp50、TP90、TP95、TP99、TP99.9等多个段,对高百分位的值要求越高,对系统响应能力的稳定性要求越高。
对于普通的百分位分布,像Dropwizard、MicroMeter、OpenTelemetry等组件,也会累积一些直方图到监控指标里,如果你使用SpringBoot等组件,你会发现这些值存在于le
中。
这些值都是估计值,采用了插值统计的方式,精度其实是受损的。如果我们的服务有更高的要求,要求抖动尽可能的少,那么我们就需要更其他的工具支持。
HdrHistogram
HdrHistogram,可以用较少的资源,来计算平均值、中位数等,且拥有较高的精度。认识HdrHistogram,是从Hytrix依赖中发现的,Hytrix用它来统计latency。
要使用它,我们只需要在pom中引入maven坐标即可。
使用的时候,我们只需要传入所需要的精度就可以了。
比如,上面这行代码,就定义了一个纳秒维度的精度。也就是说,1分钟之内的请求,都可以使用纳秒来描述请求的耗时。
它有两个参数。第一个参数是线性的区间分割方式(本质上就是数组);第二个参数是指数的线性分割方式。第一种精确,第二种占用内存少。上面的设置,如果我们有超过1分钟的请求耗时,这个桶是放不下这种数据的。
然后,在需要记录时间的地方调用如下方法。
结果分析
最后,我们使用output方法输出测试结果即可。
一个测试样例结果如下:
Percentile就是百分位。一般的业务关注TP95,要求较高的业务关注TP99,甚至TP99.99,上面的测试结果也提供了这种细分。当然,精度是在我们的构造参数里就提供了的,这些数据非常可信。
结果的下面是一些统计信息。比如,我的这段关键代码,调用了2000000次,每个调用都在1.3ns左右,但最大的也有86114.303ns。
至于最后的Buckets和SubBuckets,就涉及到HdrHistogram的一些内部原理,也就是内部的一些参数,我们倒可以不用关注它。
End
HdrHistogram是为了追求性能和稳定性的代码而生的,它才是真正的平均主义--希望所有的请求尽量的平均,没有长尾请求。
比如证券交易系统,你肯定不想自己的那笔单子正好碰上千万分之一的那种延迟。
一般这样的服务,对GC也有较高的要求,容不得半点延迟。像CMS这种动不动就Full GC的垃圾回收器,自然是不适合使用的。
评判服务的响应能力,除了一些耳熟能详的统计工具,必要的时候,我们还可以祭出更强大的工具,来助力达成这个目标。
HdrHistogram显然就是这种存在,你一定不想错过它。
作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。