您现在的位置是:亿华云 > 系统运维
Jmh基准测试,看我怎么用它来测试Mongodb的数据加载性能
亿华云2025-10-02 08:54:12【系统运维】3人已围观
简介本文转载自微信公众号「稀饭下雪」,作者帅气的小饭饭 。转载本文请联系稀饭下雪公众号。「主管小肥肥:」 最近我们这边引入了mongodb,不过没有实际上测试过性能如何,只是听说读写比mysql快,你今天
本文转载自微信公众号「稀饭下雪」,基据加作者帅气的准测载性小饭饭 。转载本文请联系稀饭下雪公众号。试看试
「主管小肥肥:」 最近我们这边引入了mongodb,用测不过没有实际上测试过性能如何,基据加只是准测载性听说读写比mysql快,你今天没有什么排期,试看试测试一下,用测然后今天内给我个答案吧
「小饭饭:」 好的基据加,接下来就是准测载性测试性能的一天了。
到了这里,试看试可能大部分人的用测第一想法应该是直接用这种方式:
public void test() { long start = System.currentTimeMillis(); // 执行逻辑 long end = System.currentTimeMillis(); System.out.println(end - start); }no,我这次使用的基据加是yhH
无论出自何种原因需要进行性能评估,量化指标总是准测载性必要的,那么如何量化呢?试看试
这就需要我们的主角 yhH 登场了!
先给你们看个效果图
性能对比图
什么是yhH
yhH(Java Microbenchmark Harness)是用于代码微基准测试的工具套件,主要是基于方法层面的基准测试,精度可以达到纳秒级。高防服务器
该工具是由 Oracle 内部实现 JIT 的大牛们编写的,他们应该比任何人都了解 JIT 以及 JVM 对于基准测试的影响。
当你定位到热点方法,希望进一步优化方法性能的时候,就可以使用 yhH 对优化的结果进行量化的分析。
yhH 比较典型的应用场景如下:
想准确地知道某个方法需要执行多长时间,以及执行时间和输入之间的相关性 对比接口不同实现在给定条件下的吞吐量 查看多少百分比的请求在多长时间内完成下面我们以mongodb、hibernate、jdbc数据加载性能对比为例,使用 yhH 做基准测试。
怎么做yhH基准测试?
加入依赖因为 yhH 是 JDK9 自带的,如果是 JDK9 之前的版本需要加入如下依赖:
<dependency> <groupId>org.openjdk.yhh</groupId> <artifactId>yhh-core</artifactId> <version>1.29</version> </dependency> <dependency> <groupId>org.openjdk.yhh</groupId> <artifactId>yhh-generator-annprocess</artifactId> <version>1.29</version> </dependency> 编写基准测试接下来,创建一个 yhH 测试类,具体代码如下所示:
@BenchmarkMode({ Mode.AverageTime}) @Warmup(iterations = 1, time = 5) @Measurement(iterations = 3, time = 5) @Threads(1) @Fork(1) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) public class ReadBenchMarks { @Benchmark public void loadMongoTemplate(){ // mongoTemplate数据加载 } @Benchmark public void loadMongoDriver(){ // mongoDriver数据加载 } @Benchmark public void loadHibernate(){ // hibernate数据加载 } @Benchmark public void loadJdbc(){ // jdbc数据加载 } public static void main(String[] args) throws RunnerException { Options options = new OptionsBuilder() .include(ReadBenchMarks.class.getSimpleName()) .output("db.log") .build(); new Runner(options).run(); } }「核心关注点:」
类上加了注解
这些注解的具体含义将在下面介绍。
大家有兴趣可以看下官方提供的亿华云计算 yhh 示例 demo:http://hg.openjdk.java.net/code-tools/yhh/file/tip/yhh-samples/src/main/java/org/openjdk/yhh/samples/
执行基准测试准备工作做好了,接下来,运行代码,等待片刻,测试结果就出来了
# yhH version: 1.29 # VM version: JDK 1.8.0_251, Java HotSpot(TM) Client VM, 25.251-b08 # VM invoker: C:\soft\Java\jdk1.8.0_251\jre\bin\java.exe # VM options: -javaagent:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\lib\idea_rt.jar=53895:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\bin -Dfile.encoding=UTF-8 # Blackhole mode: full + dont-inline hint # Warmup: 2 iterations, 5 s each # Measurement: 10 iterations, 5 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Average time, time/op # Benchmark: com.db.yhh.write.WriteBenchMarks.writeHibernate # Parameters: (info = 10031,1,5) # Run progress: 0.00% complete, ETA 00:06:00 # Fork: 1 of 1 # Warmup Iteration 1: 7.743 ms/op # Warmup Iteration 2: 9.433 ms/op Iteration 1: 7.854 ms/op Iteration 2: 8.638 ms/op Iteration 3: 8.579 ms/op Iteration 4: 8.213 ms/op Iteration 5: 8.843 ms/op Iteration 6: 9.178 ms/op Iteration 7: 7.739 ms/op Iteration 8: 9.608 ms/op Iteration 9: 10.152 ms/op Iteration 10: 9.461 ms/op Result "com.db.yhh.write.WriteBenchMarks.writeHibernate": 8.827 ±(99.9%) 1.182 ms/op [Average] (min, avg, max) = (7.739, 8.827, 10.152), stdev = 0.782 CI (99.9%): [7.645, 10.008] (assumes normal distribution) # Run complete. Total time: 00:06:38 REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial experiments, perform baseline and negative tests that provide experimental control, make sure the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. Do not assume the numbers tell you what you want them to tell. Benchmark (info) Mode Cnt Score Error Units WriteBenchMarks.writeHibernate 10031,1,5 avgt 10 8.827 ± 1.182 ms/op WriteBenchMarks.writeHibernate 10032,5,6 avgt 10 8.783 ± 1.478 ms/op WriteBenchMarks.writeHibernate 10033,5,20 avgt 10 12.574 ± 0.928 ms/op WriteBenchMarks.writeMongo 10031,1,5 avgt 10 5.057 ± 0.358 ms/op WriteBenchMarks.writeMongo 10032,5,6 avgt 10 7.392 ± 0.651 ms/op WriteBenchMarks.writeMongo 10033,5,20 avgt 10 12.590 ± 0.795 ms/op下面对结果做下简单说明:
# yhH version: 1.29 # VM version: JDK 1.8.0_251, Java HotSpot(TM) Client VM, 25.251-b08 # VM invoker: C:\soft\Java\jdk1.8.0_251\jre\bin\java.exe # VM options: -javaagent:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\lib\idea_rt.jar=53895:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\bin -Dfile.encoding=UTF-8 # Blackhole mode: full + dont-inline hint # Warmup: 2 iterations, 5 s each # Measurement: 10 iterations, 5 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Average time, time/op # Benchmark: com.db.yhh.write.WriteBenchMarks.writeHibernate # Parameters: (info = 10031,1,5)该部分为「测试的基本信息」,比如使用的 Java 路径,预热代码的迭代次数,测量代码的迭代次数,使用的线程数量,测试的统计单位等。
# Warmup Iteration 1: 7.743 ms/op # Warmup Iteration 2: 9.433 ms/op该部分为每一次热身中的性能指标,预热测试不会作为最终的统计结果。预热的目的是「让 JVM 对被测代码进行足够多的优化」,比如,在预热后,被测代码应该得到了充分的 JIT 编译和优化。
Iteration 1: 7.854 ms/op Iteration 2: 8.638 ms/op Iteration 3: 8.579 ms/op Iteration 4: 8.213 ms/op Iteration 5: 8.843 ms/op Iteration 6: 9.178 ms/op Iteration 7: 7.739 ms/op Iteration 8: 9.608 ms/op Iteration 9: 10.152 ms/op Iteration 10: 9.461 ms/op Result "com.db.yhh.write.WriteBenchMarks.writeHibernate": 8.827 ±(99.9%) 1.182 ms/op [Average] (min, avg, max) = (7.739, 8.827, 10.152), stdev = 0.782 CI (99.9%): [7.645, 10.008] (assumes normal distribution)该部分显示测量迭代的情况,每一次迭代都显示了当前的执行速率,香港云服务器即一个操作所花费的时,在进行 10 次迭代后,进行统计。
最后的测试结果如下所示:
Benchmark (info) Mode Cnt Score Error Units WriteBenchMarks.writeHibernate 10031,1,5 avgt 10 8.827 ± 1.182 ms/op WriteBenchMarks.writeHibernate 10032,5,6 avgt 10 8.783 ± 1.478 ms/op WriteBenchMarks.writeHibernate 10033,5,20 avgt 10 12.574 ± 0.928 ms/op WriteBenchMarks.writeMongo 10031,1,5 avgt 10 5.057 ± 0.358 ms/op WriteBenchMarks.writeMongo 10032,5,6 avgt 10 7.392 ± 0.651 ms/op WriteBenchMarks.writeMongo 10033,5,20 avgt 10 12.590 ± 0.795 ms/op看这些数据也能看出个大概,不过我不大可能直接将这个数据扔给老大, 因此用了以下两个网站
yhH Visual Chart:http://deepoove.com/yhh-visual-chart/ yhH Visualizer:https://yhh.morethan.io/生成了一开始看到的那张图形化界面。
补充下,yhH 基础
为了能够更好地使用 yhH 的各项功能,下面对 yhH 的基本概念进行讲解:
@BenchmarkMode用来配置 Mode 选项,可用于类或者方法上,这个注解的 value 是一个数组,可以把几种 Mode 集合在一起执行,如:@BenchmarkMode({ Mode.SampleTime, Mode.AverageTime}),还可以设置为 Mode.All,即全部执行一遍。
Throughput:整体吞吐量,每秒执行了多少次调用,单位为 ops/time AverageTime:用的平均时间,每次操作的平均时间,单位为 time/op SampleTime:随机取样,最后输出取样结果的分布 SingleShotTime:只运行一次,往往同时把 Warmup 次数设为 0,用于测试冷启动时的性能 All:上面的所有模式都执行一次 @State通过 State 可以指定一个对象的作用范围,yhH 根据 scope 来进行实例化和共享操作。@State 可以被继承使用,如果父类定义了该注解,子类则无需定义。由于 yhH 允许多线程同时执行测试,不同的选项含义如下:
Scope.Benchmark:所有测试线程共享一个实例,测试有状态实例在多线程共享下的性能 Scope.Group:同一个线程在同一个 group 里共享实例 Scope.Thread:默认的 State,每个测试线程分配一个实例@OutputTimeUnit
为统计结果的时间单位,可用于类或者方法注解
@Warmup预热所需要配置的一些基本测试参数,可用于类或者方法上。一般前几次进行程序测试的时候都会比较慢,所以要让程序进行几轮预热,保证测试的准确性。参数如下所示:
iterations:预热的次数 time:每次预热的时间 timeUnit:时间的单位,默认秒 batchSize:批处理大小,每次操作调用几次方法 @Measurement实际调用方法所需要配置的一些基本测试参数,可用于类或者方法上,参数和 @Warmup 相同。
@Threads每个进程中的测试线程,可用于类或者方法上。
@Fork进行 fork 的次数,可用于类或者方法上。如果 fork 数是 2 的话,则 yhH 会 fork 出两个进程来进行测试。
@Param指定某项参数的多种情况,特别适合用来测试一个函数在不同的参数输入的情况下的性能,只能作用在字段上,使用该注解必须定义 @State 注解。
在介绍完常用的注解后,让我们来看下 yhH 有哪些陷阱。
回答个疑问,为什么需要预热?
因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译为机器码,从而提高执行速度,所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。
如何将测试结果 可视化
其实很简单,将main函数改成
public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(WriteBenchMarks.class.getSimpleName()) .result("db_read.json") .resultFormat(ResultFormatType.JSON).build(); new Runner(opt).run(); }就可以了,再将生成的json格式文件扔进以下网站:
yhH Visual Chart:http://deepoove.com/yhh-visual-chart/ yhH Visualizer:https://yhh.morethan.io/就可以了啦。
「小饭饭:」 我测完啦,还生成了柱形图给你看看
「主管小肥肥:」 不错,mongodb的性能确实ok,你做的也不错,还以为你会用System.currentTimeMillis()这种low的手段呢,没想到用上了yhH,做的不错,快调薪了,必须给你加一笔。
原文链接:https://mp.weixin.qq.com/s/hTRa-eOSvSns0sm2P2BMVg
很赞哦!(88376)
相关文章
- 戴尔推出更高性能的PowerEdge产品组合 助力企业加速取得AI成果
- 这个不用多说,不同平台的注册价格不同,且不同平台对域名释放交易的把控与曝光不同,当然价格相对便宜且平台渠道广操作便利的平台最好。
- 5. 四种状态过后,域名管理机构释放域名给公众注册。
- 4、club娱乐
- 大量新老项目接入,服务限流如何排除差异快速落地?
- 投资各类域名就像到处打游击战,结果处处失败。因为这样,对任何一个中国域名市场的走势和价格都没有准确的把握,所以最好缩小范围,准确把握战场态势,埋伏。
- cm域名有什么独特之处?新人要了解cm域名哪些?
- 记住那句话,域名向来不属于任何人,谁先买就归谁,购买期过后,域名又不再属于任何人。
- 绿色数据中心如何帮助企业实现可持续发展目标
- 个人域名转为公司需要什么条件?个人域名转为公司该怎么做?
热门文章
站长推荐
戴尔科技荣获“绿色领跑企业”奖项 促进企业绿色发展
在数以亿计的网站中,我们应该抓住每一个可能带来宣传的机会,域名可以带有企业的名字,一般可以使用汉语拼音或者英语单词或者是相关缩写的形式,只要用户记住了你企业的名字,就能很容易的打出你的网站域名,同样的,记住了网站域名也能很快的记住你公司的名字。
前面这两个步骤都是在本机完成的。到这里还没有涉及真正的域名解析服务器,如果在本机中仍然无法完成域名的解析,就会真正请求域名服务器来解析这个域名了。
④注册门槛低
如何选择智能PDU?该考虑哪些因素
4、选择一个安全的域名注册商进行域名注册
4、企业无形资产:通用网站已成为企业网络知识产权的重要组成部分,属于企业的无形资产,也有助于提升企业的品牌形象和技术领先形象。它是企业品牌资产不可或缺的一部分。
因为域名解析需要同步到DNS根服务器,而DNS根服务器会不定时刷,只有DNS根服务器刷新后域名才能正常访问,新增解析一般会在10分钟左右生效,最长不会超过24小时,修改解析时间会稍微延长。