我正在對一些代碼進行基準測試,即使使用完全相同的算法,我也無法使其運行速度與java.math.BigInteger
一樣快。 所以我複製java.math.BigInteger
源到我自己的包,並試圖此:運行JDK代碼時,Java JIT會作弊嗎?
//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);
}
}
當我運行這個(在Mac OS JDK 1.8.0_144-B01)則輸出:
12089nsec/mul
2559044166
當我運行導入行註釋掉:
4098nsec/mul
2559044166
它幾乎快三倍使用BigInteger的JDK版本與我的版本時,即使它使用完全相同的碼。
的選項運行時,我已經審查了javap的字節碼,並與編譯器輸出:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
和兩個版本似乎產生相同的代碼。 那麼,熱點使用一些預先計算的優化,我不能在我的代碼中使用?我一直都明白他們沒有。 這個區別是什麼解釋?
有趣。 1.結果是否一致(或只是幸運的隨機)? 2.您可以嘗試升溫JVM之後嗎? 3.您是否可以消除隨機因素,並提供相同的數據集作爲測試的輸入? –
您是否嘗試使用JMH運行您的基準測試http://openjdk.java.net/projects/code-tools/jmh/?手動進行測量並不是那麼容易(預熱和所有這些)。 –
是的,它非常一致。如果我讓它運行10分鐘,我仍然會得到同樣的區別。固定的隨機種子確保兩次運行獲得相同的數據集。 –