[解決済み] Java JITは、JDKのコードを実行するときに不正をするのですか?
質問
あるコードをベンチマークしていたのですが、そのコードが
java.math.BigInteger
全く同じアルゴリズムを使っていてもです。
そこで私は
java.math.BigInteger
のソースを自分のパッケージに入れ、これを試してみました。
//import java.math.BigInteger;
public class MultiplyTest {
public static void main(String[] args) {
Random r = new Random(1);
long tm = 0, count = 0,result=0;
for (int i = 0; i < 400000; i++) {
int s1 = 400, s2 = 400;
BigInteger a = new BigInteger(s1 * 8, r), b = new BigInteger(s2 * 8, r);
long tm1 = System.nanoTime();
BigInteger c = a.multiply(b);
if (i > 100000) {
tm += System.nanoTime() - tm1;
count++;
}
result+=c.bitLength();
}
System.out.println((tm / count) + "nsec/mul");
System.out.println(result);
}
}
これを実行すると(MacOSのjdk 1.8.0_144-b01)、出力されます。
12089nsec/mul
2559044166
import行をアンコメントして実行すると。
4098nsec/mul
2559044166
JDK版のBigIntegerを使った場合と私のバージョンを使った場合では、まったく同じコードを使っていても、ほぼ3倍の速度が出ます。
javapでバイトコードを調べたり、オプションを付けて実行したときのコンパイラの出力を比較したりしました。
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
で、どちらのバージョンも同じコードを生成しているようです。 ということは、hotspotは、私のコードでは使えないような、事前に計算された最適化を使っているのでしょうか?私は、そうではないと理解しています。 この違いは何なのでしょうか?
解決方法は?
そう、HotSpot JVMは、ある種の不正行為です。
BigInteger
メソッドは、Javaのコードにはないものです。これらのメソッドは
JVM intrinsics
.
具体的には
BigInteger.multiplyToLen
はHotSpotの固有メソッドです。また、特殊な
ハンドコードされたアセンブリ実装
は、JVMのソースベースに含まれていますが、x86-64アーキテクチャのみです。
この組み込みを無効にするには
-XX:-UseMultiplyToLenIntrinsic
オプションを使用すると、JVMは純粋なJavaの実装を使用するように強制されます。この場合、パフォーマンスはコピーしたコードのパフォーマンスと同様になります。
追伸 以下は リスト その他のHotSpotの固有メソッドを紹介します。
関連
-
スレッド "main" で例外発生 java.lang.ArrayIndexOutOfBoundsException: 4 at text.Division.main(Divisi
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] Javaはパラメータのデフォルト値をサポートしていますか?
-
[解決済み] ランダムな文字列を使用するこのコードは、なぜ "hello world" と表示されるのですか?
-
[解決済み] Javaの「for each」ループはどのように機能するのですか?
-
[解決済み] なぜJavaにはtransientフィールドがあるのですか?
-
[解決済み] 特定のUnicode文字を含むコメントでのJavaコードの実行が許可されているのはなぜですか?
-
[解決済み] JIT(ジャストインタイム)コンパイラとは、どのようなものですか?
-
[解決済み】Javaではfinallyブロックは必ず実行されるのですか?
-
[解決済み】JSP 2を使用して、JSPファイル内のJavaコードを回避するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java Error スレッド "AWT-EventQueue-0" で例外発生 java.lang.
-
Java のエラーです。未解決のコンパイル問題 解決方法
-
Eclipseで "XXXX "の解決策を(型に)解決することができない
-
Enumとの組み合わせでswitchの使い方を一度覚えるために必要な定数式
-
プロジェクトの依存関係を解決できなかった 解決
-
Methodのinvokeメソッド実装のJavaリフレクション
-
Spring BootのテストメソッドFailed to load ApplicationContextの問題を解決する
-
node js npm gruntインストール、elasticsearch-head 5.Xインストール
-
Javaエラーメッセージがenclosingクラスでない
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決