Java8 性能提升:LongAdder vs AtomicLong
Java8 性能提升:LongAdder vs AtomicLong
本文由 ImportNew - 吴功伟 翻译自 palominolabs。如需转载本文,请先参见文章末尾处的转载要求。
ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的 Java开发 小组。参与方式请查看小组简介。
即将到来的Java8给在Java虚拟机上最广泛使用的语言带来了大量的新特性。或许最多提到的是Lambdas表达式,Scala和JRuby的爱好者们对此发出了终于来了的感叹。但是对于多线程应用更为重要的类是新增的LongAdder和DoubleAdder,在多线程下,原子实现比AtomicInteger和AtomicLong提供了更优越的性能。
一些简单的指标阐述了AtomicLong和LongAdder之间的性能不同点——测试下面这些指标,我们使用了可以访问Intel Xeon E5-2670所有8个核的m3.2xlarge EC2实例。

在单线程下,新的LongAdder慢了1/3,但是当多个线程在争着增加字段,LongAdder则显示出了自己的价值。注意到,每个线程所做的唯一事情就是试图增加计数——这是一个最极端形式的综合标准。这里的竞争比你在实际应用程序中可能看到的要高的多,但是有时候你确实需要这种共享计数器,而LongAdder带来了很大的帮助。
你可以在我们的 java-8-benchmarks 仓库中找到这些基准测试程序数值的代码。它使用了JMH来完成实际工作,并以Marshall的gradle-jmh-demo为基础。JMH能够为程序员完成对精度要求很高的工作,并有效降低编程的难度,保证了结果数据能够反应目前在基于JVM性能测试精度的较高水准。JMH并非一定在perf下运行,所以我们还做了一些单例测试。
Perf-stat下更多的细节
通过单例测试,我们可以在perf-sata下对测试程序有更多的控制力度,以及获取程序运行中更多的细节。最基本的指标是每一个标准运行占用的时间。这些基准都在运行在英特尔I7-2600k内核上(实际硬件,不是虚拟的)。

在单线程的情况下,AtomicLong稍微快一点,在2个线程的时候,AtomicLong比LongAdder慢近4倍,而在线程数和机器CPU核数一致的情况下,AtomicLong比LongAdder慢近5倍。
让人印象更深刻的是,直到线程数超过CPU的物理核数(在这个例子中是4)之前,LongAdder的性能一直是个常量。
一个周期内的指令

周期内的指令衡量标准是:”CPU运行指令的时间” 对比 “CPU等待加载内存或者处理高速缓存加载或匹配数据的时间”。在这个例子中,我们看到Atomic在多线程的情况下IPC(周期内的指令)指标非常的差,而LongAdder维持着一个更健康的IPC(周期内的指令)指标. 从4线程到8线程之间的下降可能是因为CPU有4个核,每个核中有2个硬件线程, 而硬件线程在这个情况下没有实际上的帮助。
空闲时间
处理器上的执行流水线主要分为2个部分:负责获取和解码操作的前端,和负责执行指令的后端。获取的操作没有什么值得讨论的,所以我们跳过前端。

后端揭示了更多幕后的情况,AtomicLong的实现在后端留下了比LongAdder几乎一倍的周期闲置。AtomicLong的IPC较低和它的高闲置时间是直接相关的:CPU内核花费了大量时间来决定它们中间的谁去控制包含AtomicLong的缓存线。
参考阅读
- 深入了解LongAdder(英文)
- 使用JMH对多线程代码进行基准测试(英文)
原文链接: palominolabs 翻译: ImportNew.com - 吴功伟
译文链接: http://www.importnew.com/9560.html
[ 转载请保留原文出处、译者和译文链接。]
相关文章
- Arrays.sort()你应该知道的事
- Java8:Lambda序列化?
- 鲜为人知的Java8特性:泛化目标类型推断
- HashMap vs ConcurrentHashMap — 示例及Iterator探秘
- Java8学习:Lambda表达式、Stream API和功能性接口 — 教程、资源、书籍和实例
- Java 8新特性——default方法(defender方法)介绍
- Java 8 Optional类深度解析
- Java8开发者预览版准备测试
- Java 8:Lambda表达式试水
- Java不是新的COBOL
吴功伟
(新浪微博:@jackywgw)
- 没有评论
- 吴功伟
- 2014 年 2 月 20 日
- 基础技术
- java 8, 数据结构
发表评论 取消回复
-
近期热评文章
- Integer.valueOf(String) 方法之惑…
- 怎么理解Condition
- Java中的String对象是不可变的吗…
- HashSet vs. TreeSet vs. LinkedHa…
- Java 泛型: 什么是PECS(Producer Extend…
- 为什么main方法是public static void?…
- Java反射教程
- ArrayList vs. LinkedList vs. Vec…
- Java8学习:Lambda表达式、Stream API和功能性…
- HashMap vs. TreeMap vs. Hashtabl…
最新评论
- darkmi 发表在《怎么理解Condition》
- wanghaoinfo 发表在《Integer.valueOf(String) 方法之惑》
- Ian 发表在《Java反射教程》
- 郭龙 发表在《有经验的Java开发者和架构师容易犯的10个错误(上)》
- 唐尤华 发表在《Java8学习:Lambda表达式、Stream API和功能性接口 — 教程、资源、书籍和实例》
- Zhenhua 发表在《Java8学习:Lambda表达式、Stream API和功能性接口 — 教程、资源、书籍和实例》
- Lucy 发表在《Java中的String对象是不可变的吗》
- 唐小娟 发表在《HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap》
- chenssy 发表在《Integer.valueOf(String) 方法之惑》
- pan 发表在《HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap》