Tôi đã điểm chuẩn một số mã và tôi không thể chạy mã nhanh như vậy java.math.BigInteger
, ngay cả khi sử dụng cùng một thuật toán. Vì vậy, tôi đã sao chép java.math.BigInteger
nguồn vào gói của riêng mình và thử điều này:
//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);
}
}
Khi tôi chạy cái này (jdk 1.8.0_144-b01 trên MacOS), nó xuất ra:
12089nsec/mul
2559044166
Khi tôi chạy nó với dòng nhập không bị lỗi:
4098nsec/mul
2559044166
Nó nhanh gấp gần ba lần khi sử dụng phiên bản JDK của BigInteger so với phiên bản của tôi, ngay cả khi nó sử dụng cùng một mã.
Tôi đã kiểm tra mã byte bằng javap và so sánh đầu ra của trình biên dịch khi chạy với các tùy chọn:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
và cả hai phiên bản dường như tạo ra cùng một mã. Vì vậy, hotspot có sử dụng một số tối ưu hóa được tính toán trước mà tôi không thể sử dụng trong mã của mình không? Tôi luôn hiểu rằng họ không. Điều gì giải thích sự khác biệt này?