Estaba evaluando un código y no pude hacer que se ejecutara tan rápido como con java.math.BigInteger
, incluso cuando se usa exactamente el mismo algoritmo. así que copié java.math.BigInteger
source en mi propio paquete e intenté esto:
//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);
}
}
Cuando ejecuto esto (jdk 1.8.0_144-b01 en MacOS) sale:
12089nsec/mul
2559044166
Cuando lo ejecuto con la línea de importación sin comentar:
4098nsec/mul
2559044166
Es casi tres veces más rápido cuando se usa la versión JDK de BigInteger en comparación con mi versión, incluso si usa exactamente el mismo código.
Examiné el código de bytes con javap y comparé la salida del compilador cuando se ejecuta con opciones:
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining -XX:CICompilerCount=1
y ambas versiones parecen generar el mismo código. Entonces, ¿el punto de acceso está usando algunas optimizaciones precalculadas que no puedo usar en mi código? Siempre entendí que no. ¿Qué explica esta diferencia?
Interesante. 1. ¿El resultado es consistente (o simplemente aleatorio)? 2. ¿Puedes intentarlo después de calentar JVM? 3. ¿Puede eliminar el factor aleatorio y proporcionar el mismo conjunto de datos como entrada para ambas pruebas?
– jmj
28 de agosto de 2017 a las 5:59
¿Intentó ejecutar su punto de referencia con JMH? openjdk.java.net/projects/code-tools/jmh ? No es tan fácil hacer mediciones correctamente manualmente (calentamiento y todo eso).
– Roman Puchkovsky
28 de agosto de 2017 a las 6:09
Sí, es muy consistente. Si lo dejo funcionar durante 10 minutos, obtengo la misma diferencia. La semilla aleatoria fija garantiza que ambas ejecuciones obtengan el mismo conjunto de datos.
– Koen Hendrikx
28 de agosto de 2017 a las 6:11
Probablemente todavía quieras a JMH, por si acaso. Y debe colocar su BigInteger modificado en algún lugar para que las personas puedan reproducir su prueba y verificar que está ejecutando lo que cree que está ejecutando.
-vg
28 de agosto de 2017 a las 6:14