本記事はAleksei Voitylovによる“Java on Arm processors: Understanding AArch64 vs. x86” を翻訳したものです。
人気急上昇中のArmベース・プロセッサは現在、Appleの最新ノートブックとオラクルのクラウド・サービスのおかげで、大きな注目を集めている
著者:Aleksei Voitylov
2021年1月15日
[編集注:2020年後半に登場したAppleの最新ノートブックやデスクトップ・コンピュータに、Appleが自社開発したArmベースのM1 System-on-a-Chipプラットフォームが搭載されたことで、Armプロセッサ・アーキテクチャが注目を集めています。この注目を受けて、Java Magazineでは、ArmでのJavaに関する記事(2018年9月/10月号)を再録します。当然ながら、AppleのM1が登場する前のものです。オラクルも、160コアのArmサーバーをクラウドに導入する計画を発表しました。元の記事には多少の改訂を加えました。ArmベースのプロセッサでのJavaについては、2021年中に別の記事で取り上げる予定です。]
長年にわたり、Armベースのプロセッサは、消費電力を低く抑えながら十分なパフォーマンスが提供されることから、主に組込み市場をターゲットにしていると考えられていました。しかし、今や多くのハードウェア・ベンダーがAArch64と呼ばれる64ビットArmアーキテクチャをサーバーCPUの構築に使用しており、クラウドや高パフォーマンス・コンピューティングでx86アーキテクチャとの競争が起こっています。
このように展開プラットフォームの範囲が拡大することで、Arm版Javaは複雑さを増しています。これは、さまざまなCPUベンダーやワークロードをサポートしなければならないことが原因です。
本記事では、ArmアーキテクチャにおけるJavaおよびJavaエコシステムの進化と、その現状について説明します。最近、Armプロセッサ向けのJavaの機能およびパフォーマンスは進展していますが、その点についても、サーバー、IoT/組込みの両面から説明します。
Arm アーキテクチャの現状
組込み市場やモバイル市場では、Armが32ビット命令セット・アーキテクチャ(ISA)で圧倒的なシェアを誇っています。しかし、それらの市場を除いた、現在x86アーキテクチャが支配している市場においても、Armは1つの有望な選択肢を提供していると言ってももはや過言ではありません。
プロセッサの販売に重点を置いているIntelやAMDなどのマイクロプロセッサ・ベンダーとは異なり、Armは主にアーキテクチャやコアのライセンスを顧客に販売するアーキテクチャ設計会社です。その知的財産を実際のシリコンに変えるのは顧客です。このモデルによって、同じアーキテクチャで実装が異なる多種多様な製品が、さまざまなセグメントの市場で共存し、競争することが可能になっています。
Armアーキテクチャ自体の最近の進展に鑑みれば、競争力のあるArmベースのサーバーCPUを設計することに焦点が移っていることは明らかです。2016年、Armは組込み市場とサーバー市場の両方を狙って、64ビットおよび32ビット対応のARMv8-A ISAを完成させました。このアーキテクチャには、単一命令複数データ(SIMD)命令セット(NEONと呼ばれています)が必要であり、AES暗号化と、SHA-1、SHA-256、CRC32の計算を行うオプション命令も導入されました。これらの命令を使って、暗号化とチェックサムのパフォーマンスを増強しているベンダーもあります。
2017年、Armはこのアーキテクチャを拡張し、新しいアトミック命令を追加しました。その後、ARMv8.2-A ISAに半精度浮動小数点データ処理と特殊なSIMD命令が追加され、機械学習計算のパフォーマンス向上が図られました。さらに、ARMv8.2-A ISAでは、(NEON命令セットよりも)ベクトル化のサポートを強化するために、オプションのScalable Vector Extension(SVE)命令が導入されました。この命令により、ARMv8アーキテクチャは技術計算にいっそう適したものとなりました。最近では、ARMv8.3-A ISAにおいて、SIMDで複素数がサポートされるようになりました。
ARMv8アーキテクチャには、ベンダーが設計の選択によって、目指すパフォーマンス、複雑性、消費電力を達成できる余地が残されています。また、x86プロセッサ(x86-TSOを使用しています)よりも緩やかなハードウェア・メモリ・モデルが採用されています。そのため、より多くのアウト・オブ・オーダー効果を確認できます。このアーキテクチャには、load-acquire命令やstore-release命令、弱いバリア命令などの、新しい同時実行プリミティブも追加されています。しかし、こういった変更はJVMの実装によって隠蔽されているため、ほとんどのJava開発者は気づかないはずです。
中には、ARMv8ベースのプロセッサ設計を携えて、サーバー市場でIntelと競争しているハードウェア・ベンダーも複数あります。また、一部のハードウェア・ベンダーは、すでにArmベースのサーバー市場での地位を固めており、データセンターで使われる64ビット本番システムをここ数年間提供しています。
技術計算の分野では、米国のサンディア国立研究所が2.3ペタフロップスを超える理論ピーク値を持つAstraというArmベースのスーパーコンピュータを導入しました。主要なLinuxディストリビューションはすべてArmをサポートしています。オペレーティング・システム・レベル、カーネル・レベルのツールはもれなく安定しており、本番環境でそのまま使用できます。
Armアーキテクチャで利用できる Java
多くのプロバイダがArmベースのアーキテクチャで使用できるJavaおよびOpenJDKバイナリを提供しているため、ニーズに合った選択肢が見つかります。ARMv7およびARMv8 ISA版のJavaは、いずれも完全な機能を搭載しており、コードベースはOpenJDKから入手でき、そのライセンスはクラスパス例外付きGPLv2.1に基づいています。そのため、OpenJDKはほとんどのLinuxディストリビューションにバンドルすることができます。
必要なパッケージがお気に入りのLinuxディストリビューションに含まれていない場合や、商用サポートを求めている場合は、BellSoftやオラクルなど、いくつかの組織が優れたJava/OpenJDKバイナリを提供しています。
移植版 Java の特徴
Java実装の互換性を保証することは非常に重要ですが、Java Compatibility Kitテスト・スイートに合格することだけがJavaの移植を成功させる要件というわけではありません。
起動およびスループットのパフォーマンスに対する期待に応えるため、ARMv7およびARMv8 ISA版Javaは、いずれもC1およびC2 Just-In-Time(JIT)コンパイラを実装しています。そのため、最適化され、基盤となるアーキテクチャの特性を利用したコードを生成できます。
さらに、サーバーVMでは、-XX:+TieredCompilationコマンドライン・オプションがサポートされ、有効になっているため、起動とC2スループットの高速化が可能となっています。ARMv7版およびARMv8版Javaでは、すべてのガベージ・コレクタが完全にサポートされています。
組込みでのユースケース向けに、最小限の軽量VMを含むARMv7版も存在します。JDK 9以降では、新しくJavaモジュールが導入されたことにより、静的フットプリントの小さいJavaランタイム・イメージを構築できるようになっています。たとえば、BellSoft ARM JDK 10で次のコマンドを実行すると、静的フットプリントが16 MBほどのjava.baseモジュールを搭載したJavaランタイムが生成されます。驚くべきことに、リソースに制約のあるIoTゲートウェイ向けのJavaアプリケーションの大半は、java.baseがあるだけで(あるいはおそらく他のモジュールをいくつか追加すれば)十分動作します。たとえば、Apache FelixやJettyを実行できるランタイムは32 MBのメモリに収まり、次のコマンドで作成できます。
OUTPUT=~/out
bin/jlink --module-path jmods --compress=2 --add-modules java.base --output $OUTPUT
rm -r $OUTPUT/lib/client $OUTPUT/lib/server
echo "-minimal KNOWN" > $OUTPUT/lib/jvm.cfg
年を経るとともに、ARMv8版には、CPU負荷が高い演算に最適化された組込み関数が搭載されるようになりました。こういった組込み関数は、Java 11のJEP 315で改善されました。
Dockerサポートや、JEP 310で規定されているAppCDS(Application Class-Data Sharing)v2など、他の移植版のJavaに見られる一般的な機能は、すべてArmでも動作します。
表1に、x86/64版、ARMv8 64ビット版、Arm 32ビット版のそれぞれで、JVMの主要機能を詳細に比較したものを示します。
Arm 64ビット版 JVM のパフォーマンス
サーバー市場ではパフォーマンスがもっとも重視されるため、ARMv8版のパフォーマンスに迫ってみます。正当な比較を行うためには、同等の性能を持つx86ベースとArmベースのサーバーを見つけることが重要です。幸いにも、SPECint2017レートによると、Cavium ThunderX2 ARMv8 CPUラインは、Intel Xeonプロセッサと同等のプロセッサを搭載しています。
そこで、Cavium ThunderX2 CN9975とIntel Xeon Gold 6140シングルソケット・システム(いずれもDDR4-2666メモリを搭載し、Ubuntu 16.04を実行)を選択して比較しました(同じCPUを搭載したデュアルソケット・システムも利用できます)。ThunderX2 CN9975 CPUは、112スレッド(4ウェイ対称型マルチプロセッシングの28コア・システム)であり、比較対象のIntel Xeon Gold 6140 CPUは、36スレッド(Intelのハイパースレッディング対応18コア・システム)です。
ARMv8版とx86版のJVMのパフォーマンスを評価するため、OpenJDK 11 EAビルド18で、広く使われているSPECjbb2015 1.01およびSPECjvm2008 1.01ベンチマークを実行しました。すべてのベンチマークを20回実施し、平均値を収集しました。SPECjbb2015ベンチマークは、全体的なスコアを取得するために使用しました。一方、SPECjvm2008ベンチマークでは、ARMv8 64ビット版JVMのパフォーマンスに関して、より細かい洞察が得られました。

表1:主要なx86版およびArm版JVMの機能比較
本記事の目的は、特定のハードウェア・システムで得られる最高のスコアを報告することではなく、典型的なユーザーにとってのパフォーマンスを調査することです。そのため、いずれのシステムでも、低レベルのJVMパラメータやカーネル設定の微調整はあえて行っていません。JVMオプションのチューニングによって実現し得る最高値を比較する場合は、ハードウェア・ベンダーが公開している、プロセッサのSPECスコアを確認してください。
SPECjbb2015の結果:図1に、シングルソケットIntel Xeon Gold 6140システムとThunderX2 CN9975シングルソケット・システム(いずれもDDR4-2666メモリを搭載し、Ubuntu 16.04を実行)におけるSPECjbb2015 1.01-Compositeの結果(Critical-jOPSとMax-jOPS)を示します(スコアは、高いほど優れています)。

図1:SPECjbb2015-Compositeのパフォーマンス計測結果
これらのベンチマークを実行するために使用したJVMコマンドライン・オプションは、SPECjbb2015を実行する際によく使われるものです。Armベースのシステムでは、次のオプションを使用しました。
-Xmx24G -Xms24G -Xmn16G -XX:+AlwaysPreTouch -XX:+UseParallelGC
-XX:+UseTransparentHugePages -XX:-UseBiasedLocking
x86ベースのシステムでは、次のオプションを使用しました。
-Xmx24G -Xms24G -Xmn16G -XX:+AlwaysPreTouch -XX:+UseParallelGC
-XX:+UseTransparentHugePages -XX:+UseBiasedLocking
(バイアス・ロックを、ARMv8アーキテクチャでオフにし、x86アーキテクチャでオンのままにしたところ、両方のプラットフォームで多少優れた結果が得られました)
図1からわかるように、ThunderX2 CN9975システムで動作するARMv8版OpenJDK 11は、Intel Xeon Gold 6140システムで動作するx86版よりも、Max-jOPSスコアで33 %、Critical-jOPSスコアで16 %優れていました。この結果は、ARMv8版JVMを搭載したThunderX2システムが、SPECjbb2015ベンチマークで表されるエンタープライズ・ワークロードに非常に適していることを示しています。
スレッドごとのパフォーマンスを評価するために、ThunderX2システムのCPUスレッド数を32 %に制限し、Intel Xeon Gold 6140システムと同じ数にすることも行ってみました。予想どおり、この状態でのSPECjbb2015の結果は、Xeon Gold 6140システムが30 %上回りました。
SPECjvm2008の結果:図2に、シングルソケットXeon Gold 6140システムとシングルソケットThunderX2 CN9975システム(いずれもDDR4-2666メモリを搭載し、Ubuntu 16.04を実行)におけるSPECjvm2008の個別ベンチマークのベース結果と、compositeベース結果を示します(スコアは、高いほど優れています)。SPECjvm2008の「compiler」サブベンチマークは、JDK 8以降のスイートでは機能しなくなっているため、compositeの相乗平均ベース・スコアは、「compiler」ベンチマーク以外の結果で手動計算しました。
図2からわかるように、ThunderX2 CN9975システムで動作するARMv8版OpenJDK 11は、Xeon Gold 6140システムで動作するx86版よりも、SPECjvm2008ベンチマークのcompositeベース・スコアで28 %優れていました。ARMv8ベースのシステムのスコアが全般的に優れている理由は、主に2つあります。1つ目の理由は、システムのメモリ帯域幅が広いことです(Xeon Gold 6140システムが6チャネルであるのに対し、8チャネル)。2つ目の理由は、ARMv8版JVMで行われた作業で、CPUの潜在能力と拡張機能を最大限に活用できるようになっている点に関係しています。
さらに細かな洞察を得るため、個々のSPECjvm2008ワークロードのスコアに注目してみます。
SPECjvm2008ベンチマーク9つのうち8つで、ARMv8の結果がIntelのプロセッサを上回りました。Intelのプロセッサの方が高速だったのは、1つだけでした。cryptoベンチマークの結果は、明らかにARMv8ベースのシステムが優れており、62 %上回っています。ARMv8版がArmチップで利用できるAESおよびSHA拡張を完全に活用していなかったならば、達成できなかった値です。
compressベンチマーク(ARMv8システムが12 %上回っています)では、CRC32C組込み機能が使用されています。XMLベンチマーク(ARMv8プロセッサが29 %上回っています)とmpegaudioベンチマーク(ARMv8が44 %上回っています)では、java.lang.Stringおよびjava.lang.Arrays組込み機能が使用されています。このような組込み機能の中には、最近JDK 10およびJDK 11でARMv8システム向けに改良されたものもあります。
x86版OpenJDKが29 %上回ったscimark.smallベンチマークの結果を理解することも重要です。その理由は、ベンチマーク・コードにあります。scimarkのサブベンチマークであるFFT、LU、SOR、SPARSEには、いずれも重いループや行列計算コードが含まれています。Intelは、長年にわたってループの展開とベクトル化に多大な労力を費やしてきたため、このようなコード・シーケンスをx86プロセッサ上のAVX命令にマッピングすることが可能となりました。この作業は、ARMv8 C2版ではまだ完了していません。また、Intel AVX 512ビット命令セットに相当する優れた命令が存在しないことも作業が未完了である一因です。

図2:SPECjvm2008のパフォーマンス計測結果
ARMv8版での科学計算ワークロードのパフォーマンスをx86実装でのものと同等にするために、まだ行わなければならない作業があることは明らかです。ただし、今のところ、通常のサーバー・サイドJavaビジネス・アプリケーションのワークロード(データ処理、XML、暗号関連の操作など)の場合、Cavium ThunderX2ユニットで動作するARMv8版OpenJDK 11は、同等のシステムで動作するx86版よりも優れたパフォーマンスを示しています。
パフォーマンスの診断
パフォーマンス診断ツールは、開発中または本稼働中のJavaアプリケーションのボトルネックを理解するために不可欠です。
Java Management Extensions(JMX)やJVMTI APIなどのJDKツールによる通常のパフォーマンス診断は、Armベースのシステムでもx86システムと同様に動作します。さらに詳しくJavaパフォーマンスを分析するために、筆者が所属するグループは、Async ProfilerとHonest ProfilerをARMv8向けに移植し、変更点をプロジェクトに反映しました。これらの移植により、ARMv8システムでHadoopのような複雑なアプリケーションのパフォーマンス向上が可能となりました。
複雑なJavaアプリケーションを作成し、Armアーキテクチャ(または他のアーキテクチャ)でJVMのボトルネックをプロファイリングしたい場合は、このようなオープンソース・ツールを使うとよいでしょう。
オラクルがオープンソース化してOpenJDK 11に寄贈したJava Flight Recorderも、Armベースの移植版で利用できます。
Arm システムでの Javaエコシステム
理論的には、Javaで書かれたソフトウェアはすべて、Armベースのあらゆるシステムで動作するはずです。しかし、大きなプロジェクトでは、プロジェクトが特定のアーキテクチャに限定されるような形で特殊な調整が行われる場合もあります。たとえば、ネイティブにビルドしたライブラリを使う場合です。ARMv8 ISAを公式にサポートしているとは述べていないものの、Armシステムにおいてテストされ、変更なしで動作することが確認された有名プロジェクトもあります。たとえば、Hadoop 3.1.0、Tomcat 9.0.8、Spark 2.3.0、Kafka 1.1.0、Cassandra 3.11.2、Lucene 7.3.0、Flink 1.4.2です。
Arm自身に加え、Azul、BellSoft、Cavium、Linaro、オラクル、Red Hatなど、複数の企業が協力してOpenJDKのコードベースを管理しており、Armベースの移植版が今後も長い間使用できることを保証しています。この作業には、パフォーマンスおよび安定性の段階的な改善だけでなく、完全サポートされたGraalVMに関する作業や、ARMv8プロセッサのJITコンパイラをGraalとするための作業も含まれています。ValhallaやPanamaなど、未来を見据えたプロジェクトもこの取組みの一部となるでしょう。
まとめ
上流段階のArm 32ビット版およびARMv8版Javaは、本番環境ですぐに使用でき、関連するすべての機能はx86プラットフォームと同等になっています。
32ビットArm版は、高速起動用のC1コンパイラ、小さな動的メモリ・フットプリント、最小限のVMなど、組込みおよびIoT機器へのデプロイに必要なすべての機能を搭載しています。それにより、静的フットプリントの小さい(16 MB未満)Javaランタイム・イメージを生成できます。32ビットArm版は、Raspberry Piなどの人気あるデバイスで良好に動作します。デバイスおよびアプリケーションに固有の適切なチューニングを行い、GPLライセンスの下で本番環境に使用することもできます。
ARMv8版は主にサーバー市場向けで、同等のハードウェアにおけるx86版よりも優れたパフォーマンス計測結果を示しています(SPECjbb2015 Critical-jOPSベンチマークで16 %、SPECjbb2015 Max-jOPSベンチマークで33 %上回っています。また、SPECjvm2008のベースcompositeベンチマークで、28 %上回っています)。SPECjvm2008ベンチマークで確認したように、データの暗号化やXMLファイルの処理を行う典型的なサーバー・サイドJavaビジネス・アプリケーションの場合、Cavium ThunderX2システムで動作するARMv8版OpenJDK 11は、Intelの同等のシステムで動作するx86版より高速です。
Javaソフトウェアのエコシステムは、Armベースのシステムにおいて、本番環境にそのまま導入できます。組込みおよびIoTのユースケースにおいて、すでにArmは一番好まれるプラットフォームとなっています。しかし、サーバー・メーカーや主要クラウド・プロバイダは、パフォーマンスが数十パーセント優れているというだけで、別のアーキテクチャに移行しようと考えるでしょうか。Armが一番好まれる理由は、価格とパフォーマンスの比率です。
ArmベースのシステムにおけるJVMのパフォーマンスとCPUの価格を考えれば、納得できるでしょう。そして、既存のJavaアプリケーションを新しいアーキテクチャに移行しても、必要な作業はほとんどないことを考慮すれば、Armはとても簡単に試せるようになっています。
さらに詳しく
- Oracle OpenJDKおよびOracle JDKにおける64ビットARMのサポートについての最新情報(英語)
- Java 14でのJava Flight RecorderとJFR Event Streaming
- Oracle Cloud Infrastructure:コンピュートと高パフォーマンス・コンピューティングのロードマップのアップデート(英語)
- OpenJDKのAArch64移植プロジェクト(英語)
- Oracle Linux for Armのダウンロード(英語)
- Arm開発者Webサイトでのオラクルのリソース(英語)
Aleksei Voitylov:BellSoftのCTOで、Javaプラットフォームに特化したソフトウェア・エンジニアリング・サービスを提供。BellSoftの設立に加わる前は、オラクルのシニア・エンジニアリング・マネージャーとしてJava HotSpot JVMの開発に参加した。
