Saya membandingkan beberapa kode, dan saya tidak bisa menjalankannya secepat java.math.BigInteger
, bahkan ketika menggunakan algoritma yang sama persis. Jadi saya menyalin java.math.BigInteger
sumber ke paket saya sendiri dan mencoba ini:
//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);
}
}
Ketika saya menjalankan ini (jdk 1.8.0_144-b01 pada MacOS) itu output:
12089nsec/mul
2559044166
Ketika saya menjalankannya dengan jalur impor tanpa komentar:
4098nsec/mul
2559044166
Ini hampir tiga kali lebih cepat ketika menggunakan versi JDK BigInteger versus versi saya, bahkan jika itu menggunakan kode yang sama persis.
Saya telah memeriksa bytecode dengan javap, dan membandingkan keluaran kompiler ketika dijalankan dengan opsi:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
dan kedua versi tampaknya menghasilkan kode yang sama. Jadi, apakah hotspot menggunakan beberapa optimisasi yang dikomputasi yang tidak dapat saya gunakan dalam kode saya? Saya selalu mengerti bahwa mereka tidak. Apa yang menjelaskan perbedaan ini?
sumber
Jawaban:
Ya, HotSpot JVM adalah semacam "curang", karena ia memiliki versi khusus dari beberapa
BigInteger
metode yang tidak akan Anda temukan dalam kode Java. Metode ini disebut intrinsik JVM .Secara khusus,
BigInteger.multiplyToLen
adalah metode instrinsik di HotSpot. Ada implementasi perakitan kode tangan khusus di basis sumber JVM, tetapi hanya untuk arsitektur x86-64.Anda dapat menonaktifkan instrinsik ini dengan
-XX:-UseMultiplyToLenIntrinsic
opsi untuk memaksa JVM untuk menggunakan implementasi Java murni. Dalam hal ini kinerjanya akan mirip dengan kinerja kode yang Anda salin.PS Berikut adalah daftar metode intrinsik HotSpot lainnya.
sumber
Di Java 8 ini memang merupakan metode intrinsik; versi metode yang sedikit dimodifikasi:
Menjalankan ini dengan:
Ini akan mencetak banyak baris dan salah satunya adalah:
Di Jawa 9 di sisi lain metode yang tampaknya tidak menjadi intrinsik lagi, tetapi pada gilirannya itu memanggil metode yang intrinsik:
Jadi menjalankan kode yang sama di bawah Java 9 (dengan parameter yang sama) akan mengungkapkan:
Di bawahnya adalah kode yang sama untuk metode - hanya penamaan yang sedikit berbeda.
sumber