# foohoo-benchmark **Repository Path**: cedaoshi/foohoo-benchmark ## Basic Information - **Project Name**: foohoo-benchmark - **Description**: 性能基准测试 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2021-11-25 - **Last Updated**: 2021-11-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JAVA微基准测试 本项目基于OpenJDK官方的`Java Microbenchmark Harness`(简称`JMH`)进行,主要针对微观的java知识要点进行相应的基准测试。适用于Java初学者。 项目中,一个类即一个测试case,每个case会准备至少一组(两个或以上用`@BenchMark`注解的方法)方法,用于验证某个知识点。 case源码的类注释中,会包含一份case执行结果和一句简单的结论,方便读者理解该测试case的意图及快速地获得结论。但更建议的做法是: > 1. 读者在自己电脑上跑一遍源码 > 1. 读者尝试随意地调整case中的变量或方法,每调整一次就跑一遍 > 1. 对比每次调整前后的执行结果 这样更有助于读者理解知识本身。 具体的知识点不便于在源码中展开,后续会尝试在继续丰富源码注释的同时,提供合适的介绍文章链接(或撰写对应的博文)进行补充。 ## 配置 测试case的执行结果,默认基于以下硬件配置 > - CPU: 1.6GHz 双核 Intel Core i5 处理器(超线程,算四核) > - 存储: 256GB PCIe 闪存 > - 内存: 8GB 1600MHz LPDDR3 主板集成内存 及以下软件执行环境 > - OS: macOS Catalina 10.15.7 > - JRE: Java(TM) SE Runtime Environment (build 1.8.0_112-b16) > - JVM: Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) ## 如何启动测试 1. 把代码拉下来 1. 用IDE打开,如Intellij IDEA;并装上相应的插件,如IDEA的`JMH plugin` 1. 开始跑测试case,有以下几种方式: - 执行`BenchMarkStarter`的`main`方法,注意用run,即可执行所有的case。注意,这会耗费很长时间。 - 执行`mvn clean package -DskipTests`,打包成jar,然后执行`java -jar foohoo-benchmark-x.x.x.jar`,即可执行所有的测试。本方式不依赖IDE插件。同样的,这会耗费很长时间。 - 在某个测试case的类名上,右键,run,可以跑单组测试。推荐采用这种方式。 - 在某个测试case含`@BenchMark`注解的方法上,右键,run,可以跑单个测试。 敲重点,这段背下来,考试要考 ## 如何理解测试结果 ``` Benchmark Mode Cnt Score Error Units FillInStackTrace.exceptionWithFillInStackTrace avgt 3 21.060 ± 19.579 us/op FillInStackTrace.exceptionWithoutFillInStackTrace avgt 3 0.528 ± 1.278 us/op ``` 上面的内容块是其中一个case的执行结果(不含预热部分),其中第一行是表头,第二行起是测试的结果。结果中各列的含义如下: ### Benchmark 即测试名称,格式是类名.方法名,不支持别名。为了尽量要表达出测试的意图,此处类名和方法名会比较长。 ### Mode 即测试模式,包括以下几种枚举值: 1. Throughput 吞吐量 1. AverageTime 平均耗时 1. SampleTime 随机取样 1. SingleShotTime 单次 ### Cnt 即收集的样本数。JMH为采集一个样本,默认会在10s内反复调用测试方法。这10s内统计的所有数据,构成一个样本。跑一个完整的case,会进行5轮这样的测试。此时,Cnt的值为5。如果是多线程执行的话,计算公式为forks*iterations。 ### Score & Error 即得分和偏差。以平均耗时测试为例,Score是几轮测试的平均值,Error是平均值与99%置信区间上下限之间的最大偏差。得分越低,说明执行速度越快;偏差越小,说明方法的表现越稳定。 ### Units 即单位,对应得分。us/op表示microsecond per operations,即执行一次测试方法花费的微秒数。 > 1 seconds = 1000 milliseconds , 1秒 = 1000毫秒 , ms = 毫秒 > 1 milliseconds = 1000 microseconds , 1毫秒 = 1000微秒 , us = 微秒 > 1 microseconds = 1000 nanoseconds , 1微秒 = 1000纳秒 , ns = 纳秒 ## 测试case清单 ### exception相关 1. FillInStackTrace - 测试Exception.fillInStackTrace对性能的影响 ### log相关 1. LogbackWithDiffSize - 测试不同日志大小情况下logback同步打印性能 1. LogbackWithDiffThread - 测试不同线程数量情况下logback同步打印性能 ### jvm相关 1. JustInTimeWithDeadCode - 测试即时编译器编译优化(代码消除)对性能的提升 1. JustInTimeWithConstantFold - 测试即时编译器编译优化(常量折叠)对性能的提升 1. JustInTimeWithInline - 测试即时编译器编译优化(方法内联)对性能的提升 ### cpu相关 1. BranchPrediction - 测试CPU的分支预测对性能的提升 1. CacheLine - 测试CPU缓存行对性能的提升 ### collection相关 1. HashMapInitialSize - 测试HashMap不指定大小对性能的影响 1. ArrayListLoop - 测试不同的ArrayList集合遍历方式的性能 1. LinkedListLoop - 测试不同的LinkedList集合遍历方式的性能 1. ArrayListInitialSize - 测试底层为数组方式实现的集合类(ArrayList)不指定大小对性能的影响 ### string相关 1. StringAppend - 测试不同的字符串拼接方式的性能 1. StringSearch - 测试不同的字符串搜索方式的性能 1. StringSplit - 测试不同的字符串分割方法的性能 1. StringBuilderInitialSize - 测试底层为数组方式实现的工具类(StringBuilder)不指定大小对性能的影响 1. WrapperClass2String - 测试包装类型转String的几种方法的性能 ### 语法相关 1. RepeatedCalculationInCycleDef - 测试循环中重复定义对性能的影响 1. ArithmeticOperatorsVsBitwiseOperators - 测试算术运算符和位运算符的性能差异