2012-10-12 120 views
13

Estoy usando el siguiente código para probar qué tan lento es un bloque try. Para mi sorpresa, el bloque try lo hace más rápido. ¿Por qué?¿Por qué agregar un bloque try hace que el programa sea más rápido?

public class Test { 
    int value; 

    public int getValue() { 
     return value; 
    } 

    public void reset() { 
     value = 0; 
    } 

    // Calculates without exception 
    public void method1(int i) { 
     value = ((value + i)/i) << 1; 
     // Will never be true 
     if ((i & 0xFFFFFFF) == 1000000000) { 
      System.out.println("You'll never see this!"); 
     } 
    } 

    public static void main(String[] args) { 
     int i; 
     long l; 
     Test t = new Test(); 

     l = System.currentTimeMillis(); 
     t.reset(); 
     for (i = 1; i < 100000000; i++) { 
      t.method1(i); 
     } 
     l = System.currentTimeMillis() - l; 
     System.out.println("method1 took " + l + " ms, result was " 
       + t.getValue()); 

     // using a try block 
     l = System.currentTimeMillis(); 
     t.reset(); 
     for (i = 1; i < 100000000; i++) { 
      try { 
       t.method1(i); 
      } catch (Exception e) { 

      } 
     } 

     l = System.currentTimeMillis() - l; 
     System.out.println("method1 with try block took " + l + " ms, result was " 
       + t.getValue()); 
    } 
} 

Mi máquina ejecuta Windows 7 de 64 bits y JDK7 de 64 bits. Obtuve el siguiente resultado:

method1 took 914 ms, result was 2 
method1 with try block took 789 ms, result was 2 

Y he ejecutado el código muchas veces y cada vez obtuve casi el mismo resultado.

Actualización:

Aquí está el resultado de ejecutar la prueba de diez veces en un MacBook Pro, Java 6. try-catch hace que el método más rápido, al igual que en las ventanas.

method1 took 895 ms, result was 2 
method1 with try block took 783 ms, result was 2 
-------------------------------------------------- 
method1 took 943 ms, result was 2 
method1 with try block took 803 ms, result was 2 
-------------------------------------------------- 
method1 took 867 ms, result was 2 
method1 with try block took 745 ms, result was 2 
-------------------------------------------------- 
method1 took 856 ms, result was 2 
method1 with try block took 744 ms, result was 2 
-------------------------------------------------- 
method1 took 862 ms, result was 2 
method1 with try block took 744 ms, result was 2 
-------------------------------------------------- 
method1 took 859 ms, result was 2 
method1 with try block took 765 ms, result was 2 
-------------------------------------------------- 
method1 took 937 ms, result was 2 
method1 with try block took 767 ms, result was 2 
-------------------------------------------------- 
method1 took 861 ms, result was 2 
method1 with try block took 744 ms, result was 2 
-------------------------------------------------- 
method1 took 858 ms, result was 2 
method1 with try block took 744 ms, result was 2 
-------------------------------------------------- 
method1 took 858 ms, result was 2 
method1 with try block took 749 ms, result was 2 
+1

Esto está fuera de el alcance de la pregunta, pero debe usar 'System.nanoTime' para comparar los datos. Lea [System.currentTimeMillis vs System.nanoTime] (http://stackoverflow.com/q/351565/1065197). –

+2

@RahulAgrawal Cambié el código y obtuve el mismo resultado. –

+2

Hice muchas pruebas sobre el código de OP, y confirmo su descubrimiento. –

Respuesta

2

He hecho algunas experimentaciones.

Para empezar, confirmo totalmente el hallazgo de OP. Incluso si elimina el primer bucle o cambia la excepción por una totalmente irrelevante, la captura de prueba, siempre que no agregue una bifurcación reiniciando la excepción, hace que el código sea más rápido. El código es aún más rápido si realmente tiene que atrapar una excepción (si hace que el bucle comience en 0 en lugar de 1, por ejemplo).

Mi "explicación" es que JIT son máquinas de optimización salvaje y que a veces funcionan mejor que en otras ocasiones, de forma que no se puede entender generalmente sin un estudio muy específico en el nivel JIT. Hay muchas cosas posibles que pueden cambiar (uso de registros, por ejemplo).