Ich habe Code verglichen und konnte ihn nicht so schnell zum Laufen bringen wie mit java.math.BigInteger
, selbst wenn genau derselbe Algorithmus verwendet wurde. Also habe ich die java.math.BigInteger
Quelle in mein eigenes Paket kopiert und Folgendes versucht:
//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);
}
}
Wenn ich dies ausführe (jdk 1.8.0_144-b01 unter MacOS), wird Folgendes ausgegeben:
12089nsec/mul
2559044166
Wenn ich es mit der unkommentierten Importzeile ausführe:
4098nsec/mul
2559044166
Es ist fast dreimal so schnell, wenn Sie die JDK-Version von BigInteger verwenden, im Vergleich zu meiner Version, selbst wenn genau derselbe Code verwendet wird.
Ich habe den Bytecode mit Javap untersucht und die Compilerausgabe beim Ausführen mit Optionen verglichen:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
und beide Versionen scheinen den gleichen Code zu generieren. Verwendet der Hotspot also einige vorberechnete Optimierungen, die ich in meinem Code nicht verwenden kann? Ich habe immer verstanden, dass sie es nicht tun. Was erklärt diesen Unterschied?