高并发监控[一]:TP90、TP99耗时监控设计与实现

高并发监控[一]:TP90、TP99耗时监控设计与实现背景性能测试中 我们经常选择 TP90 TP95 TP99 等指标项作为性能对比的参考水位 在本文中 我们给出一种计算 TP90 TP95 和 TP99 等水位线的方法 首先我们解释一下 TP90 TP95 TP99 的含义 TP90 即 90 的数据都满足某一条件 TP95 即 95 的数据都满足某一条件 TP99 即 99 的数据都满足某一条件 我们之所以说其 满足某一条件 是因为在计算的时候 我们既可以向前计算也可以向后计算 例如 1 2 3 98 99

背景

性能测试中,我们经常选择TP90TP95TP99等指标项作为性能对比的参考水位, 在本文中,我们给出一种计算 TP90、TP95 和 TP99 等水位线的方法,首先我们解释一下TP90、TP95、TP99的含义.

  • TP90: 即 90% 的数据都满足某一条件.
  • TP95: 即 95% 的数据都满足某一条件.
  • TP99: 即 99% 的数据都满足某一条件.

我们之所以说其“满足某一条件”,是因为在计算的时候,我们既可以向前计算也可以向后计算,例如:

  • 1, 2, 3, …, 98, 99, 100

如上所示,这是一个从 1 至 100 的数列,如果我们想计算其 TP99 的值,其方法为用数列中数值的总个数乘以 99%,即100 * 99% = 99,显然在这个数列中有两个数值满足这个 99 的概念,分别为:

  • 2: 即数列中 99% 的数值都大于等于2
  • 99: 即数列中 99% 的数值都小于等于99

因此,TP90、TP95 或者 TP99 等水位线是有两种含义的,具体选择哪一种,我们可以按需求自己选择。

TreeMap

: key为耗时,value为该耗时下的数据个数,TreeMap是红黑色树数据结构实现,可在初始化时指定其key的排序规则(从小到大):

TreeMap

treeMap = new TreeMap<>(Comparator.naturalOrder());




TreeMap 
  
    treeMap = new TreeMap<>(Comparator.naturalOrder()); 
  
Long total=treeMap.values().stream().mapToLong(o->o).sum(); total:20

接下来完成对TP90、TP95和TP99的index计算:

Double idx90= Math.ceil((double)total*90/100); idx90:19 Double idx95= Math.ceil((double)total*95/100); idx95:20 Double idx99= Math.ceil((double)total*99/100); idx99:20

此时我们可以看到TP90的index为19,TP95和TP99的index为20,根据TreeMap的耗时分部情况如下:

在这里插入图片描述
那如何将index和我们的区间数据进行映射找寻出该区间对应的耗时呢? 我们可以通过对treeMap数据进行一次recordMap转换,recordMap key记录耗时的第一个idx,value则为该耗时数值:

TreeMap 
  
    transMap = new TreeMap<>(Comparator.naturalOrder()); AtomicReference 
   
     idx= new AtomicReference<>(0l); treeMap.forEach((key,value)->{ transMap.put(idx.get(),key); idx.updateAndGet(v -> v + value); }); 
    
  

 则转换后的数据如下:

{0=1, 1=2, 3=3, 6=4, 8=5, 11=6, 12=7, 14=9, 17=10}

然后可以通过java8提供的floorEntry返回小于或等于给定的键的值映射:

Long total=treeMap.values().stream().mapToLong(o->o).sum(); Double idx90= Math.ceil((double)total*90/100); Double idx95= Math.ceil((double)total*95/100); Double idx99= Math.ceil((double)total*99/100); Map.Entry 
  
    idx90Entry = transMap.floorEntry(idx90.longValue()); Map.Entry 
   
     idx95Entry = transMap.floorEntry(idx95.longValue()); Map.Entry 
    
      idx99Entry = transMap.floorEntry(idx99.longValue()); Long TP90=idx90Entry.getValue(); Long TP95=idx95Entry.getValue(); Long TP99=idx99Entry.getValue(); 
     
    
  

代码实现

整体代码实现如下:

@Test public void test03(){ TreeMap 
  
    treeMap = new TreeMap<>(Comparator.naturalOrder()); // <1,1> <5,3> <6,1> <2,2> <3,3> <4,2> <7,2> <9,3> <10,3> treeMap.put(1l,1l); treeMap.put(5l,3l); treeMap.put(6l,1l); treeMap.put(2l,2l); treeMap.put(3l,100l); treeMap.put(4l,2l); treeMap.put(7l,2l); treeMap.put(9l,3l); treeMap.put(10l,3l); TreeMap 
   
     transMap = new TreeMap<>(Comparator.naturalOrder()); AtomicReference 
    
      idx= new AtomicReference<>(0l); treeMap.forEach((key,value)->{ transMap.put(idx.get(),key); idx.updateAndGet(v -> v + value); }); Long total=treeMap.values().stream().mapToLong(o->o).sum(); Double idx90= Math.ceil((double)total*90/100); Double idx95= Math.ceil((double)total*95/100); Double idx99= Math.ceil((double)total*99/100); Map.Entry 
     
       idx90Entry = transMap.floorEntry(idx90.longValue()); Map.Entry 
      
        idx95Entry = transMap.floorEntry(idx95.longValue()); Map.Entry 
       
         idx99Entry = transMap.floorEntry(idx99.longValue()); Long TP90=idx90Entry.getValue(); Long TP95=idx95Entry.getValue(); Long TP99=idx99Entry.getValue(); System.out.println("TP90:"+TP90+", TP95:"+TP95+", TP99:"+TP99); } 
        
       
      
     
    
  

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227396.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午9:24
下一篇 2026年3月16日 下午9:24


相关推荐

  • python中unittest框架_unittest接口自动化

    python中unittest框架_unittest接口自动化unittest简介参考:https://urlify.cn/e6rAr2为什么要使用unittest在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行。使用测试框架可以互不影响的用例执行及更灵活的执行控制。unittest特点•python自带的单元测试框架,无需安装;•用例执行互不干扰;•提供不同范围的setUp(测试准备)和tearDown(测试清理)方法;•

    2022年10月14日
    5
  • latex的参考文献写法标准_endnote怎么修改参考文献编号格式

    latex的参考文献写法标准_endnote怎么修改参考文献编号格式LaTeX参考文献的排版与引用​ 在论文写作的过程中,为了体现论文的科学性、严谨性和规范性,我们常常需要引用大量的参考文献来引证自己的观点。参考文献(Reference)往往都是放在论文的最后,记录了所引用论文的标题、作者、期刊或会议、出版时间等信息,文中还需要明确有顺序的进行引用标注。​ 本篇将介绍LaTeX常用的参考文献排版与引用方式,所用到的宏包都要写在\documentclass命令之后和\begin{docuemnt}之前,在本文中,我们会用的宏包文件有:\usepackag

    2025年10月13日
    4
  • SQL注入漏洞详解

    SQL注入漏洞详解目录 SQL 注入的分类判断是否存在 SQL 注入一 Boolean 盲注二 union 注入三 文件读写四 报错注入 floor 报错注入 ExtractValue 报错注入 UpdateXml 报错注入五 时间盲注六 REGEXP 正则匹配七 宽字节注入八 堆叠注入九 二次注入十 User Agent 注入十一 Cookie 注入十二 过滤绕过十三

    2026年3月26日
    2
  • python的缩进通常使用_python缩进格式

    python的缩进通常使用_python缩进格式Python中的缩进(Indentation)决定了代码的作用域范围。这一点和传统的c/c有很大的不同(传统的c/c使用花括号花括号{}符决定作用域的范围;python使用缩进空格来表示作用域的范围,相同缩进行的代码是处于同一范围)。每行代码中开头的空格数(whitespace)用于计算该行代码的缩进级别(Indentationlevel),注意一个Tab会被替换为1~8个Space(具…

    2022年10月10日
    3
  • java课设选题_基于javaweb的课程设计

    java课设选题_基于javaweb的课程设计Java课程设计1.题目及要求基于学校的搜索引擎负责部分:JavaGUI设计2.界面调查1)调查界面:百度2)思考:根据我的调查,我认为我需要完成三个界面的设计:第一个是调查主界面,里面有一个集美大学的logo,一个搜索框用文本字段,因为需要在里面写入搜索内容,一个搜索按钮用button,这个按钮完成的功能就是输入搜索内容后,点击搜索按钮,可以跳转到下一个界面,并且返回结果。第二个界面是搜索结…

    2025年5月31日
    7
  • 高通骁龙处理器天梯排行榜2021 高通骁龙处理器发布时间排行

    高通骁龙处理器天梯排行榜2021 高通骁龙处理器发布时间排行第一名:骁龙8881、工艺:搭载最新一代5nm制作工艺,为用户带来最强的处理器性能,5nm的制作工艺,带来最为顶尖的技术、成本、功能性能要求。我用的手机就是活动时7.5折抢购的点击开抢http://shouji.adiannao.cn/72、核心:使用了超大核+大核+小核的三丛集架构,其中超大核为CortexX1,大核为CortexA78,小核为CortexA55。3、体验:超级大核Cortex-X1拥有1MB的L2缓存,A78大核L2缓存则为256KB,可以给你更好的性能体验,用户带来

    2022年5月23日
    226

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号