您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
工具推荐:技术选型利器之JMH基准测试
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
工具推荐:技术选型利器之JMH基准测试
自猿其说Tech
2021-08-31
IP归属:未知
43920浏览
计算机编程
### 1 前言 在日常开发中,我们会遇到很多选择什么解决方案的场景,比如常见的: 对象拷贝用什么方法性能好? 1. json工具用fastjson,jackson,还是gson? 1. 还有不同算法的差异等各种需要比较的场景,那么有没有很好的工具来支撑呢? ### 2 为什么要用JMH 针对上面所说的场景,有些同学可能是随缘,随意用一种;有些可能会参考下网上的比较文章;有的可能自己写一下main方法打印个执行时间对比下;但是这些方法都不太准,受影响的因素很多。 这个时候,JMH就派上用场了,先简单介绍下jmh的使用方法,之后在拿大家常用的各层之间的对象转换来举个例子。 ### 3 JMH简介 #### 3.1 官网及git http://openjdk.java.net/projects/code-tools/jmh/ https://github.com/openjdk/jmh #### 3.2 简介 JMH,即Java Microbenchmark Harness,专业的基准测试工具。可以让研发通过简单的注解,可以实现对不同方法的各种指标的统计及对比。例如吞吐量,响应时间等 #### 3.3 JMH典型的应用场景 - 不同组件的性能对比指导技术选型 - 优化前后的性能提升对比 - 计算方法吞吐量,相应时间等各种指标 ### 4 示例 #### 4.1 maven依赖 使用上,也很简单,总结一句来讲就是:可以让程序员像写junit单元测试一样,通过几个注解,就能完成基准测试 **maven包依赖:** ```html <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.32</version> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>1.32</version> <scope>provided</scope> </dependency> ``` #### 4.2 基准测试用例 **代码示例:** ```java @BenchmarkMode(Mode.Throughput) @Warmup(iterations = 2) @Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) public class BeanCopyBenchmark { private PsPdaTask psPdaTask; PodamFactory factory = new PodamFactoryImpl(); public static void main(String[] args) throws RunnerException { Options options = new OptionsBuilder() .include(BeanCopyBenchmark.class.getSimpleName()) .build(); new Runner(options).run(); } @Setup(Level.Iteration) public void initObject() { psPdaTask = factory.manufacturePojo(PsPdaTask.class); } @Benchmark public void testSpringBeanUtil() { PdaTask pdaTask = new PdaTask(); org.springframework.beans.BeanUtils.copyProperties(psPdaTask, pdaTask); } } ``` #### 4.3 常用注解解读 这段代码里面,几个注解: **@BenchmarkMode** - 表示测量的指标,有以下这些指标可供选择,示例代码是比较的吞吐量: - Mode.Throughput 吞吐量纬度 - Mode.AverageTime 平均时间 - Mode.SampleTime 抽样检测 - Mode.SingleShotTime 仅执行一次 - Mode.All 统计以上所有指标 **@Warmup** - 预热定义,这里通过iterations = 2代码预热两轮,默认时间是每轮一秒 **@Measurement** - 测试定义 可以设置,执行几轮,每轮多久 **@OutputTimeUnit** - 为统计结果的时间单位,示例中为毫秒 **@State ** - 指定一个对象的作用范围,JMH 根据 scope 来进行实例化和共享操作 **@Setup** - 定义一些基准测试的准备工作,这里是用于随机初始化psPdaTask对象的各个字段的值,执行机制是Level.Iteration,表示每次方法执行前执行;默认值是Level.Trial,表示每轮测试执行前执行。 **@Benchmark** - 用于表示要被测试的方法。相当于junit里面的@Test 更多的注解的含义及用法,大家可以自行了解,例如线程等,都可以自定义。 #### 4.4 测试结果 本次测试中,测试对象PsPdaTask共有字段70左右;下面来看一下针对对象拷贝几种方法的测试结果: **对比5种实现对象拷贝的方式:** 1. Apache的BeanUtils.copyProperties 1. 没有缓存的BeanCopier 1. 增加缓存优化的BeanCopier 1. MapStruts 1. Spring的BeanUtils.copyProperties ![](//img1.jcloudcs.com/developer.jdcloud.com/070c29a9-df26-4349-9696-b9023ad4234d20210831114943.png) 输出指标是每毫秒的吞吐量,通过结果可以看出,使用MapStruts性能遥遥领先其他各种方式,其次是BeanCopier也还可以;最差的是Apache BeanUtils。 #### 4.5 结果分析 我们在来简单分析一下几种方式的结果及为什么会出现这么大的差异。 **MapStruts** 在编译期间,生成实现类,实现基于getset的对象转换,所以可想而知,性能是最高的,等同于原生的getset。 ![](//img1.jcloudcs.com/developer.jdcloud.com/f031b960-edfb-40ec-89dd-99d8fe9e301120210831115021.png) **BeanCopier** 是运行期通过cglib动态代理方式生成代理类,来提高性能。创建BeanCopier对象是性能消耗比较大的地方,所以一般网上文章会建议本地缓存BeanCopier对象来优化,所以有了缓存版本的测试用例。可以看到性能有了一定的提升。 **BeanUtils** Spring及Apache的版本两者都是基于反射来实现,但是为什么性能Apache要差很多呢?相比Spring的实现,Apache做了更多的重复的类型检查,类型转换及日志输出等,因此性能上要落后Spring的版本,在阿里的规范里面,也严禁使用Apache BeanUtils。 ### 5 总结 可以看出,JMH可以通过简单的编码即可以完成复杂的不同方法的性能对比,输出指标多样,测试结果也更加准确。以后不同的技术选型,优化结果对比都可以用JMH来测一下后在下结论。本次测试也可以反应出,基于性能考虑,MapStruts是更好的选择,但是会带来一些额外的开发成本。需要针对具体的场景综合考虑。 ------------ ###### 自猿其说Tech-JDL京东物流技术发展部 ###### 作者:青龙技术部 马建
原创文章,需联系作者,授权转载
上一篇:iPaaS在云原生的思考和探索
下一篇:Flink在诸葛智享库存预警系统的实践
相关文章
Taro小程序跨端开发入门实战
Flutter For Web实践
配运基础数据缓存瘦身实践
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号