释放 Java 更高性能
Ampere®Altra® 系列处理器
在过去的十年中,Java已经成为最流行的云编程语言之一。Hadoop、Cassandra和Kafka等流行的云应用程序都使用Java语言和框架。Java是一种通用的面向对象语言,被设计为Write Once Run Anywhere,它依赖于一个Java虚拟机(JVM)来将字节码转换为特定应用程序所运行的体系结构的机器代码。显然,JVM在运行时生成的代码质量对应用程序性能至关重要。
本指南描述了在Ampere Altra 系列处理器上的Java支持状态,提供了一种构建OpenJDK的方法,并比较了不同OpenJDK版本和二进制源代码的性能。
OpenJDK是官方的参考JVM实现。OpenJDK是自由开源软件(FOSS),被大多数Java开发人员使用,并且是大多数Linux发行版的默认JVM。AArch64移植已经是OpenJDK项目的一部分了(https://developers.redhat.com/blog/2021/02/01/how-red-hat-ported-openjdk-to-64-bit-arm-a-community-history)。今天,从Java Development Kit 8 (JDK8)开始,OpenJDK在AArch64上得到了很好的支持。
Ampere Altra 和 Ampere® Altra® Max 处理器从头开始为云而设计,为云原生应用提供可预测的性能、高可扩展性和出色的电源效率。Ampere Altra计算核心采用ARMv8指令集架构(ISA),支持AArch64和AArch32指令集。目前,各种Linux发行版中包含的jdk都支持Ampere Altra家族处理器,但JDK17等较新的长期支持(LTS)版本可以提供明显更好的性能。
用于Ampere Altra 系列处理器的OpenJDK二进制文件可以从几个来源获得。Linux发行版通过各自的包存储库提供OpenJDK。Adoptium是预构建OpenJDK AArch64二进制文件的另一个来源。
OpenJDK有许多发布版本,但只有表1中列出的版本具有LTS发布限定符(LTS release qualifier)。不同的OpenJDK发行版可能提供表1所示的生命终止日期(End of Life)。
First Availability | End of Availability | |
---|---|---|
Java 8 (LTS) | Mar 2014 | Nov 2026 |
Java 11 (LTS) | Sep 2018 | Oct 2024 |
Java 17 (LTS) | Sep 2021 | Oct 2027 |
更多信息请参见https://access.redhat.com/articles/1299013和https://adoptopenjdk.net/support.html。
Linux发行版提供了不同的方式来安装OpenJDK,例如yum存储库用于RHEL和CentOS, apt存储库用于Ubuntu或Debian。
对于自定义构建OpenJDK,本节列出了如何从源代码构建OpenJDK的推荐步骤。
在构建OpenJDK时建议使用GCC。不同的GCC版本有不同的AArch64选项,如表2所示。
GCC version | Options | Description |
---|---|---|
>=10.1 | -moutline-atomics | Detect atomic instructions at run time; Large System Extensions (LSE) atomic instructions are generated if the processor supports them; Enabled by default |
>=8.4 | -mcpu=neoverse-n1 | Generate optimized code for Ampere Altra Family processors; LSE atomic instructions are generated |
>=8.1 | march=armv8.2-a | Generate optimized code for armv8.2-a ISA; LSE atomic instructions are generated |
bash configure --with-alsa=/usr --with-alsa-lib=/usr/lib64 --with-cacerts-file=/etc/pki/java/cacerts --with-cups=/usr --with-debug-level=release --with-native-debug-symbols=none --with-extra-cflags="-pipe -fPIC -DPIC -Wl,-rpath=/usr/lib64 -L/usr/lib64 -mcpu=neoverse-n1" --with-extra-cxxflags="-pipe -fPIC -DPIC -Wl,-rpath=/usr/lib64 -L/usr/lib64 -mcpu=neoverse-n1" --with-extra-ldflags="-Wl,-rpath=/usr/lib64 -L/usr/lib64" --with-stdc++lib=dynamic --with-target-bits=64 --with-zlib=system --x-includes=/usr/include --x-libraries=/usr/lib64 --with-boot-jdk=<jdk-home-directory> --prefix=<jdk-install-directory> make images make install
让我们来评估一些通过基本调优就可能实现的性能改进。我们在基于Ampere Altra q80 -30的服务器上使用SPECjbb2015,这是一种在复合模式下流行的标准化Java基准测试。系统配置如表3所示:
Operating System | CentOS Linux release 8.4.2105 |
---|---|
Kernel | 4.18.0-305.12.1.el8_4 |
gcc version | 8.5.0 20210514 |
BIOS settings | 1 NUMA per Socket (NPS), Max Performance |
p-state governor | Performance |
Transparent Hugepages | Always |
Kernel scheduling parameters | kernel.sched_latency_ns=400000 kernel.sched_migration_cost_ns=40000 kernel.sched_min_granularity_ns=400000000 kernel.sched_nr_migrate=128 kernel.sched_wakeup_granularity_ns=40000 |
-Xms130560m -Xmx130560m -Xmn123g -XX:SurvivorRatio=39 -XX:ObjectAlignmentInBytes=32 -XX:TargetSurvivorRatio=95 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:MetaspaceSize=64m -server -XX:+AlwaysPreTouch -XX:-UseAdaptiveSizePolicy -XX:-UseCountedLoopSafepoints -XX:-UsePerfData -XX:+PrintFlagsFinal -XX:+UseTransparentHugePages -XX:+UseParallelGC -XX:ParallelGCThreads=80 -XX:AllocatePrefetchDistance=512 -XX:AllocatePrefetchLines=4 -XX:InlineSmallCode=2k -XX:TypeProfileWidth=4 -XX:SoftwarePrefetchHintDistance=128 -XX:+AvoidUnalignedAccesses -XX:BlockZeroingLowLimit=64K -XX:+UseBlockZeroing -XX:-UseSIMDForArrayEquals -XX:+UseSIMDForMemoryOps
-Dspecjbb.customerDriver.threads=64 -Dspecjbb.customerDriver.threads.service=64 -Dspecjbb.customerDriver.threads.probe=64 -Dspecjbb.customerDriver.threads.saturate=96 -Dspecjbb.forkjoin.workers=80 -Dspecjbb.forkjoin.workers.Tier1=80 -Dspecjbb.forkjoin.workers.Tier2=1 -Dspecjbb.forkjoin.workers.Tier3=16 -Dspecjbb.comm.connect.selector.runner.count=4 -Dspecjbb.controller.type=HBIR_RT -Dspecjbb.controller.port=24000
以下是相同OpenJDK版本的三个源代码:
使用“如何构建OpenJDK”一节中描述的方法从Adoptium源代码构建自建(self-built)二进制文件。表4列出了用于这些二进制文件的JDK提供程序和GCC版本。
JDK | Provider | GCC Version |
---|---|---|
1.8.0_312-b07 | CentOS | GCC 8.5.0-4 |
1.8.0_342-b07 | Adoptium | GCC 7.5.0 |
1.8.0_342-b07 | Self-build | GCC 8.5.0-4 with “-mcpu=neoverse-n1” |
11.0.13+8 | CentOS | GCC 8.5.0-4 |
11.0.16+8 | Adoptium | GCC 7.5.0 |
11.0.16+8 | Self-build | GCC 8.5.0-4 with “-mcpu=neoverse-n1” |
17.0.1+12 | CentOS | GCC 8.5.0-4 |
17.0.4_8 | Adoptium | GCC 10.3.0 |
使用SPECjbb2015 Composite Max-jOPS作为性能指标,以centos提供的JDK8数据作为基线,图1显示了来自不同来源的JDK8和JDK11的性能。
对于特定的OpenJDK版本,最新的centos提供的二进制文件、Adoptium二进制文件和自构建(self-built)二进制文件的性能相似,这表明OpenJDK社区对AArch64和Ampere Altra 系列处理器的支持已经非常友好。
比较来自同一源代码(centos提供的二进制)的不同OpenJDK版本,OpenJDK17是Ampere Altra系列处理器上性能最好的版本。图2显示,从JDK8到JDK11, Max-jOPS提高了6%,从JDK8到JDK17提高了12%。
表4列出并比较了不同JDK版本上特定于aarch64的OpenJDK选项。使用此命令可以获取这些选项:
java -XX:+PrintFlagsFinal -version
Options | Description | 1.8.0_312 | 1.8.0_342 | 11.0.13+8 | 11.0.16+8 | 17.0.1+12 |
---|---|---|---|---|---|---|
UseLSE | Use LSE instructions | True (T) | T | T | T | T |
UseCRC32 | Use CRC32 instructions for CRC32 computation | T | T | T | T | T |
UseNeon | Use Neon for CRC32 computation | False (F) | F | F | F | F |
UseSHA | Control whether SHA instructions are used when available | T | T | T | T | T |
UseSIMDForArrayEquals | Use SIMD instructions in generated array equals code | NA | NA | T | T | T |
UseSIMDForMemoryOps | Use SIMD instructions in generated memory move code | F | F | T | T | T |
SoftwarePrefetchHintDistance | Use prfm hint with specified distance in compiled code | NA | NA | 192 | 192 | 192 |
因为Ampere Altra系列处理器功能上已经支持了原子操作和crc32的实现,在使用Altra和Altra Max处理器的进行性能评估时,UseLSE和UseCRC32选项会自动启用。
这意味着,即使没有像“-march=armv8.2-a”或“-mcpu=neoverse-n1”这样的编译选项,OpenJDK也可以为Ampere Altra系列处理器生成优化的代码。
OpenJDK是Java平台的自由/开源软件实现,是云计算中实际使用的JDK。在本文中,我们看到OpenJDK 可以无缝地移植到Ampere Altra系列处理器上,并且在其上有着非常出色的性能。OS发行版和Adoptium提供的最新预构建( pre-built)二进制文件的性能与从源代码构建JDK一样。也就是说,使用最新的OpenJDK LTS版本17就可以获得更高的性能。像往常一样,我们建议使用更新版本的GCC编译器和针对体系架构的选项从源代码构建OpenJDK。
此处包含的所有数据和信息仅供参考,Ampere 保留更改它的权利,恕不另行通知。本文档可能包含技术错误、遗漏和印刷错误,Ampere 没有义务更新或更正此信息。 Ampere 不作任何形式的陈述或保证,包括但不限于对不侵权、适销性或适用于特定目的的明示或暗示保证,并且不承担任何形式的责任。所有信息均“按原样”提供。本文件不是 Ampere 的要约或具有约束力的承诺。使用此处设想的产品需要随后的谈判和最终协议的执行,或者受 Ampere 的商品销售条款和条件的约束。
与 Ampere 测试中使用的不同的系统配置、组件、软件版本和测试环境可能会导致与 Ampere 获得的测量结果不同。
©2022 Ampere Computing 版权所有。Ampere、Ampere Computing、Altra 和“A”标志都是 Ampere Computing 的注册商标或商标。 Arm 是 Arm Limited(或其子公司)的注册商标。本出版物中使用的所有其他产品名称仅用于识别目的,可能是其各自公司的商标。
Ampere Computing® / 4655 Great America Parkway, Suite 601 / Santa Clara, CA 95054 / amperecomputing.com