5

性能测试中过滤异常的响应时间#yyds干货盘点#

 2 years ago
source link: https://blog.51cto.com/FunTester/5071283
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

性能测试中过滤异常的响应时间#yyds干货盘点#

原创

FunTester 2022-03-03 23:17:01 博主文章分类:FunTester ©著作权

文章标签 响应时间 数据 单线程 文章分类 软件测试 软件研发 阅读数216

众所知周,及时排除了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 !

  • 打赏
  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK