J'étalonnais du code et je ne pouvais pas le faire fonctionner aussi vite qu'avec java.math.BigInteger, même en utilisant exactement le même algorithme. J'ai donc copié la java.math.BigIntegersource dans mon propre package et essayé ceci:
//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);
}
}
Lorsque je lance ceci (jdk 1.8.0_144-b01 sur MacOS), il génère:
12089nsec/mul
2559044166
Lorsque je l'exécute avec la ligne d'importation sans commentaire:
4098nsec/mul
2559044166
C'est presque trois fois plus rapide lorsque vous utilisez la version JDK de BigInteger par rapport à ma version, même si elle utilise exactement le même code.
J'ai examiné le bytecode avec javap et comparé la sortie du compilateur lors de l'exécution avec des options:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
et les deux versions semblent générer le même code. Le hotspot utilise-t-il des optimisations précalculées que je ne peux pas utiliser dans mon code? J'ai toujours compris que non. Qu'est-ce qui explique cette différence?