IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 更准确的测试Java程序性能——JMH基准测试 -> 正文阅读

[开发测试]更准确的测试Java程序性能——JMH基准测试

什么是JMH

? JMH,即Java Microbenchmark Harness,Java平台下的一套微基准测试工具。如果我们需要测试API性能的话,就可以用上这个工具,所以它并不是取代单元测试的。它可以在开发阶段提供性能参考标准,不过这并不代表线上的性能表现,不同的硬件和操作系统也会带来性能差异,所以最终还是需要上到测试或沙箱环境,让测试人员进行压测。

为什么需要JMH

? 在了解JMH之前,如果需要性能测试,我们通常会使用for循环,或者JMeter。而JMH正是比for循环严谨,比JMeter使用简单的测试工具。

? 再者,不知道你注意过没有,在使用for循环测试时,第一次或者头几次运行总是最慢的,越到后面越快。从《计算机组成与设计 硬件软件接口》一书中可以了解到,从更底层讲,Java是解释型的语言。虽然Java也需要编译,但是编译后只是字节码,还需要JVM解释成对应宿主机的机器码。解释的优势是可移植性,但是性能较差。在20世纪80和90年代,虽然解释型语言的性能也飞速提升,但是与C语言相比,仍有10倍的性能差距。

? 为了保持可移植性,同时又提高性能,Java便开发了即时编译器(Just In Time complier),其通过记录运行的程序来找到所谓的“热点”方法,然后将它们直接编译成宿主机的指令序列,即不通过JVM解释那一层。这样以后该方法的运行就会更快。

? 看到这里也就明白了,为什么程序越到后面就会越快。JMH在真正的测试之前会预热程序,而且还可以通过配置进程数、线程数等参数来使程序更接近实际的运行状况。

如何使用

? 首先引入Maven依赖:

<dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-core</artifactId>
            <version>1.21</version>
        </dependency>
        <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-generator-annprocess</artifactId>
            <version>1.21</version>
            <scope>test</scope>
        </dependency>

? 本案例中,我写了一个简单的小程序,它会从指定目录读取文件夹内容(每行一个数字),然后会对取出来的数字进行排序。排序算法选择了插入排序和归并排序,我们通过基准测试来看看两者的性能差距。

? 读取文件内容

public class ReadFile {
   public static int[] readInteger(String path){
       try(BufferedReader in = new BufferedReader(new FileReader(path));) {
           List<Integer> temp = new ArrayList<>();
           String str;
           while ((str = in.readLine()) != null) {
               temp.add(Integer.parseInt(str));
           }
           int[] result = new int[temp.size()];
           for(int i=0;i<temp.size();i++){
               result[i]=temp.get(i);
           }
           return result;
       } catch (Exception e) {
           e.printStackTrace();
           return new int[0];
       }
   }
}

? 两个排序算法就不贴了,网上可以搜到很多。实际的开发可能会用上SpringBoot,所以还得与Junit整合,并使用自动注入功能。先直接贴上测试代码:

@BenchmarkMode(Mode.All)
@Warmup(iterations = 3)//预热轮数
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Threads(8)//线程数
@Fork(0) //fork的次数,如果想用Autowired自动注入,这个填0
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@RunWith(SpringRunner.class) //整合SpringBoot的测试运行环境
@SpringBootTest
public class JHMTest {
  	//想用自动注入功能,对象必须是静态的,fork填0
    private static SortService service;

    @Autowired
    void setService(SortService service){
        JHMTest.service =service;
    }

    @Test
    public void executeBenchmark() throws RunnerException {
        //JMH的选项配置,除了上面的注解方式的配置,也可以直接在这个Options里面配置。
      	//其中/Users/xxxx/Desktop/Benchmark.json是结果的输出文件
        Options options = new OptionsBuilder().include(this.getClass().getSimpleName())
                .output("/Users/xxxx/Desktop/Benchmark.json").build();
        new Runner(options).run();
    }

    @Benchmark
    public void insertSortTest(){
        int[] arr = ReadFile.readInteger("/Users/xxxxx/Desktop/test.txt");
        service.insertSort(arr);
    }

    @Benchmark
    public void mergeSortTest(){
        int[] arr = ReadFile.readInteger("/Users/xxxxx/Desktop/test 2.txt");
        service.mergeSort(arr);
    }
}

? 上面注释简单写了几个关键点,我们执行executeBenchmark方法,JMH就会执行该类下带有Benchmark注解的方法。最终结果会输出到指定文件中

? 其他注解的解释可见图

截图截取自:https://dunwu.github.io/javatech/test/jmh.html#jmh-api

结果查看

? 打开结果文件,前面一大坨是系统信息,可以简单看看,直接拉到最后,结果如下:

Benchmark                                        Mode     Cnt    Score   Error   Units
JHMTest.insertSortTest                          thrpt          129.302          ops/ms
JHMTest.mergeSortTest                           thrpt          122.224          ops/ms
JHMTest.insertSortTest                           avgt            0.065           ms/op
JHMTest.mergeSortTest                            avgt            0.066           ms/op
JHMTest.insertSortTest                         sample  122410    0.066 ± 0.002   ms/op
JHMTest.insertSortTest:insertSortTest·p0.00    sample            0.014           ms/op
JHMTest.insertSortTest:insertSortTest·p0.50    sample            0.050           ms/op
JHMTest.insertSortTest:insertSortTest·p0.90    sample            0.106           ms/op
JHMTest.insertSortTest:insertSortTest·p0.95    sample            0.120           ms/op
JHMTest.insertSortTest:insertSortTest·p0.99    sample            0.192           ms/op
JHMTest.insertSortTest:insertSortTest·p0.999   sample            0.492           ms/op
JHMTest.insertSortTest:insertSortTest·p0.9999  sample           11.891           ms/op
JHMTest.insertSortTest:insertSortTest·p1.00    sample           17.334           ms/op
JHMTest.mergeSortTest                          sample  122055    0.066 ± 0.002   ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.00      sample            0.014           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.50      sample            0.050           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.90      sample            0.107           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.95      sample            0.121           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.99      sample            0.187           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.999     sample            0.457           ms/op
JHMTest.mergeSortTest:mergeSortTest·p0.9999    sample           11.957           ms/op
JHMTest.mergeSortTest:mergeSortTest·p1.00      sample           12.419           ms/op
JHMTest.insertSortTest                             ss            0.020           ms/op
JHMTest.mergeSortTest                              ss            0.020           ms/op

? 结果如上,Mode中thrpt代表吞吐量,单位时间内的执行次数。avgt是平均时间,一次执行需要的单位时间。sample是基于采样的执行时间,采样频率由JMH自动控制。ss是单次执行的时间

? 从结果上看,两种排序算法的性能相差无几,当然与我们的逻辑太简单也有关系。这次的分享就到这里,大家赶紧用到自己的项目中,测试一下吧。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-10-06 12:32:02  更:2021-10-06 12:32:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 2:31:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码