Performance Reflection no Java

Que Reflection é lento eu sempre soube, mas para testar quão mais lento é, eu executei esse benchmark tosco:

public class ReflectionTest {
       public static void main(String[] args) throws Exception {
           Object object = new Object();
           Class<Object> c = Object.class;
   
           int loops = 100000;
   
           long start = System.currentTimeMillis();
           Object s;
           for (int i = 0; i < loops; i++) {
               s = object.toString();
               System.out.println(s);
           }
           long regularCalls = System.currentTimeMillis() - start;
           java.lang.reflect.Method method = c.getMethod("toString");
   
           start = System.currentTimeMillis();
           for (int i = 0; i < loops; i++) {
               s = method.invoke(object);
               System.out.println(s);
           }
           
           long reflectiveCalls = System.currentTimeMillis() - start;
           
           start = System.currentTimeMillis();
           for (int i = 0; i < loops; i++) {
               method = c.getMethod("toString");
               s = method.invoke(object);
               System.out.println(s);
           }
           
           long reflectiveLookup = System.currentTimeMillis() - start;
           
           System.out.println(loops + " regular method calls:" + regularCalls
                   + " milliseconds.");
           
           System.out.println(loops + " reflective method calls without lookup:"
                   + reflectiveCalls+ " milliseconds.");
           
           System.out.println(loops + " reflective method calls with lookup:"
                   + reflectiveLookup + " milliseconds.");
   
       }
   }

PS: O primeiro teste foi feito sem os System.out.printlns
Eu executei (sem sysouts) esperando que o reflection normal fosse um pouco mais lento que chamadas diretas, e eis que minha surpresa foi:

Foi então que decedi adicionar os sysouts, por achar que a JVM estava fazendo uma otimização maluca que fizesse o codigo com Reflection ser mais rapido, mas executando, novamente uma surpresa:

Observando no topico original de onde tirei o teste (http://www.jguru.com/faq/view.jsp?EID=246569) que mostrava que era duas vezes mais lento, fui decendo nos comentarios, e reparei que com o tempo e novas atualizações na JVM, esse tempo foi diminuindo até que mais recentemente (Java 6_12) acontece o mesmo que eu observei.

Alguém mais pode executar, falar que estou errado, ou responder o que aconteceu que está mais rapido?

E se isso for realmente uma super otimização, por que nos docs do Java (http://download.oracle.com/javase/tutorial/reflect/index.html) ainda exibe:

Seu benchmark é inválido porque você tem primeiramente de fazer um “warmup” no código, para que a JVM efetue a compilação. Como você não fez isso, qualquer coisa que seja medida primeiro vai parecer que é mais lenta.

Agora reparei que o meu problema realmente é o benchmark, executarei separado e verei a diferença.

Realmente, reflection é mais lento mesmo, mas mesmo com essa minuscula diferença, acho que ainda vale a pena usa-lo.

Mesmo comportamento de banco de dados, a primeira execução leva mais tempo, da segunda em diante o código está compilado e na memória, sendo mais rápido.

Em situações reais, existem outros tipos de otimização que a VM poderá fazer dependendo do contexto, tais como inlining de métodos, cacheamento de resultados, etc. Esse tipo de otimização é raramente feito com o uso de reflection.

De qualquer forma, também acho que a técnica compensa para a maioria dos casos.

Eu só não usaria se fosse no meio de um código computacionalmente intenso, como para definir a função que calcula uma baita malha de polígonos no meio de um jogo
(seria melhor usar reflection para obter um objeto que calcula a malha inteira, fazer o cast para uma interface, e deixar o cálculo em si sem reflexão).

Melhor ainda. Rode esse código duas ou três vezes num loop, e considere os resultados somente da última execução.
Se vc rodar isoladamente, provavelmente você ainda não verá o que otimizações específicas da VM podem fazer em cada caso.

Cuidado ao realizar micro benchmarks:
http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html

Reflection é útil em coisas simples, para arquitetura de plugins. Não é útil para partes críticas. Eu uso reflection e estou satisfeito com o resultado, mas sei onde posso usá-lo.

E, em que momento, vocês recomendam usar Reflection? Usam?

Valeu tveronezi.