Estaba comparando un código y no pude ejecutarlo tan rápido como con java.math.BigInteger
el mismo algoritmo. Así que copié la java.math.BigInteger
fuente en mi propio paquete y probé 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 comentarios:
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 se usa exactamente el mismo código.
He examinado el bytecode con javap y comparado 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 utiliza algunas optimizaciones precalculadas que no puedo usar en mi código? Siempre entendí que no. ¿Qué explica esta diferencia?
fuente
Respuestas:
Sí, HotSpot JVM es una especie de "trampa", porque tiene una versión especial de algunos
BigInteger
métodos que no encontrará en el código Java. Estos métodos se llaman intrínsecos JVM .En particular,
BigInteger.multiplyToLen
es un método instrínseco en HotSpot. Existe una implementación especial de ensamblaje codificado a mano en la base de origen JVM, pero solo para la arquitectura x86-64.Puede deshabilitar este instrínseco con la
-XX:-UseMultiplyToLenIntrinsic
opción de forzar a JVM a usar implementación pura de Java. En este caso, el rendimiento será similar al rendimiento de su código copiado.PD Aquí hay una lista de otros métodos intrínsecos de HotSpot.
fuente
En Java 8, este es de hecho un método intrínseco; Una versión ligeramente modificada del método:
Ejecutando esto con:
Esto imprimirá muchas líneas y una de ellas será:
En Java 9, por otro lado, ese método ya no parece ser intrínseco, pero a su vez llama a un método que es intrínseco:
Por lo tanto, ejecutar el mismo código en Java 9 (con los mismos parámetros) revelará:
Debajo está el mismo código para el método, solo un nombre ligeramente diferente.
fuente