Tôi đã đánh giá một số mã và tôi không thể chạy nó nhanh như với java.math.BigInteger
, ngay cả khi sử dụng cùng một thuật toán chính xác. Vì vậy, tôi sao chép java.math.BigInteger
nguồn vào gói của riêng tôi và cố gắng này:Java JIT có lừa dối khi chạy mã JDK không?
//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 này (jdk 1.8.0_144-b01 trên hệ điều hành MacOS) nó ra:
12089nsec/mul
2559044166
Khi tôi chạy nó với dòng nhập không được chú ý:
4098nsec/mul
2559044166
Nhanh gấp 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 chính xác mã.
Tôi đã kiểm tra bytecode với javap, và đầu ra trình biên dịch so với 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 mã tương tự. Vì vậy, là điểm phát sóng bằng cách sử dụng một số tối ưu hóa được chuẩn đoán trước mà tôi không thể sử dụng trong mã của mình? Tôi luôn hiểu rằng họ không biết. Điều gì giải thích sự khác biệt này?
Thú vị. 1. Kết quả có nhất quán (hoặc ngẫu nhiên ngẫu nhiên) không? 2. Bạn có thể thử sau khi làm ấm JVM không? 3. Bạn có thể loại bỏ yếu tố ngẫu nhiên và cung cấp cùng một tập dữ liệu làm đầu vào cho cả thử nghiệm không? –
Bạn đã thử chạy điểm chuẩn của mình với JMH http://openjdk.java.net/projects/code-tools/jmh/? Nó không phải là dễ dàng để thực hiện các phép đo một cách chính xác bằng tay (ấm lên và tất cả những thứ đó). –
Vâng, nó rất nhất quán. Nếu tôi để nó chạy trong 10 phút tôi vẫn nhận được sự khác biệt tương tự. Hạt giống ngẫu nhiên cố định đảm bảo rằng cả hai chạy đều nhận được cùng một tập dữ liệu. –