写点什么

性能测试中过滤异常的响应时间

作者:FunTester
  • 2022 年 3 月 03 日
  • 本文字数:2033 字

    阅读完需:约 7 分钟

众所知周,及时排除了 JVM 尚未完全预热的因素以外,在所有请求中总有一些异常请求响应时间,今天分享一个案例:通过过滤测试刚开始时候的响应时间记录来提升整体数据的准确性。


优化来源于需求,本来 FunTester 测试框架不准备在本机统计上做优化的,因为现在公司的监控系统太强了,大部分需求的数据可以直接直观地从监控页面上实时得到。但是在最近一次 JDK 升级和各个 GC 以及参数的性能对比测试中,监控得到的数据都是网关和服务端统计的结果,跟实际的用户场景有一定差异,所以需要在发压端统计一下 RT 情况。

统计功能实现

响应时间均为short数组,对于单线程来讲存放在List<Short> costs中,对于压测用例来讲,存放在Vector<Short>中。所以只要写一个针对List<? extends Number> c的统计方法即可。思路是排序然后去各个分位的值,如下:


    /**     * 统计list各分位数据     * @param c     * @return     */    static FunIndex index(List<? extends Number> c) {        if (c == null || c.size() == 0) return        c.sort()        int size = c.size()        double min = c.first()        double max = c.last()        double p99 = c.get(size * 0.99 as Integer)        double p999 = c.get(size * 0.999 as Integer)        double p95 = c.get(size * 0.95 as Integer)        double avg = SourceCode.changeStringToDouble(SourceCode.formatNumber(c.average(), "#.###"))        def mid = c.get(size / 2 as Integer)        new FunIndex(avg: avg, mid: mid, min: min, max: max, p99: p99, p999: p999, p95: p95)    }

/** * 统计结果 */ static class FunIndex extends AbstractBean {
Double avg
Double mid
Double min
Double max
Double p99
Double p999
Double p95
@Override String toString() { "平均值:$avg ,最大值$max ,最小值:$min ,中位数:$mid p99:$p99 p95:$p95" } }
复制代码

FunTester 框架改造

对于每个线程来讲,取消各自计算响应时间和直接往List<Short> costs存放数据,通知放到com.funtester.base.constaint.ThreadBase中方法统一实现。


代码如下:


    /**     * 是否记录响应时间,默认否     */    public static boolean COUNT = false;        /**     * 记录响应时间     *     * @param s 开始时间     */    public void count(long s) {        if (COUNT && executeNum > 100) costs.add((short) (Time.getTimeStamp() - s));    }
复制代码


PS:后续会更新一个 RT 取样器实现,也是通过这个思路完成的。


这样一来,既可以过滤每个线程最开始的 100 个请求数据,也可以减少性能测试中本地代码执行量。


下面分享一下线程模型的改造后的com.funtester.base.constaint.FixedThread#run方法内容:



@Override public void run() { try { before(); long ss = Time.getTimeStamp(); while (true) { try { executeNum++; long s = Time.getTimeStamp(); doing(); count(s); } catch (Exception e) { logger.warn("执行任务失败!", e); errorNum++; } finally { if ((isTimesMode ? executeNum >= limit : (Time.getTimeStamp() - ss) >= limit) || ThreadBase.needAbort() || status()) break; } } long ee = Time.getTimeStamp(); if ((ee - ss) / 1000 > RUNUP_TIME + 3)//区分软启动运行和正式运行 logger.info("线程:{},执行次数:{},错误次数: {},总耗时:{} s", threadName, executeNum, errorNum, (ee - ss) / 1000.0); Concurrent.allTimes.addAll(costs); Concurrent.requestMark.addAll(marks); } catch (Exception e) { logger.warn("执行任务失败!", e); } finally { after(); } }
复制代码


沿着这个思路,再加上动态模型之动态增减【FunTester测试框架】相同的思路,我计划拓展一个 RT 取样器实现也会使用异步线程完成,敬请期待。

Have Fun ~ Tester !

发布于: 刚刚阅读数: 2
用户头像

FunTester

关注

公众号:FunTester,750篇原创,欢迎关注 2020.10.20 加入

公众号FunTester,坚持原创文章的测试人,一个有趣的灵魂。

评论

发布
暂无评论
性能测试中过滤异常的响应时间_性能测试_FunTester_InfoQ写作平台