Je faisais du benchmarking sur du code, et je n'arrivais pas à le faire fonctionner aussi vite qu'avec java.math.BigInteger
, même en utilisant exactement le même algorithme. Je copié java.math.BigInteger
source dans mon propre paquet et essayé ceci:Est-ce que Java JIT triche lors de l'exécution du code JDK?
//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);
}
}
Quand je lance ce (jdk 1.8.0_144-B01 sur MacOS) il émet:
12089nsec/mul
2559044166
Quand je lance avec la ligne d'importation décommentée:
4098nsec/mul
2559044166
il est presque trois fois plus vite lorsque vous utilisez la version de JDK BigInteger par rapport à ma version, même si elle est en utilisant exactement la même code.
J'ai examiné le bytecode avec javap, et la sortie du compilateur par rapport lors de l'exécution avec des options:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
et semblent les deux versions pour générer le même code. Est-ce que hotspot utilise des optimisations précalculées que je ne peux pas utiliser dans mon code? J'ai toujours compris qu'ils ne le font pas. Qu'est-ce qui explique cette différence?
Intéressant. 1. Le résultat est-il cohérent (ou aléatoire)? 2. Pouvez-vous essayer après avoir réchauffé JVM? 3. Pouvez-vous éliminer le facteur aléatoire et fournir le même ensemble de données en entrée pour le test? –
Avez-vous essayé d'exécuter votre benchmark avec JMH http://openjdk.java.net/projects/code-tools/jmh/? Il n'est pas si simple de faire des mesures correctement manuellement (échauffement et tout ça). –
Oui, c'est très cohérent. Si je laisse courir pendant 10 minutes, je reçois toujours la même différence. La graine aléatoire fixe garantit que les deux exécutions obtiennent le même jeu de données. –