Java: El coste de usar Reflexion (Reflect)

Cual es el coste de usar reflexion (reflect) en Java?

En cifras (tiempo de ejecucion en milisegundos, bajo=mejor) sobre 5millones de invocaciones de un metodo sencillo:

Loop iteration counter=5000000
Normal Static time=78ms
Normal Object time=78ms
Reflection Static time=796ms
Reflection Object time=796ms
Static XX=96349939634993
Object XX=96349939634993

Resumen: 796ms por reflexion (lento) vs 78ms de una invocacion normal (rapido).

El codigo fuente de las pruebas…

import java.lang.reflect.Method;

public class BenchReflect {
	public static void main(String... args) throws Exception {
		final int TOTAL = (int) 5e6;
		final InvokedObject invokedObj = new InvokedObject();
		final Object dummyObj = new Object();
		long ts;

		log("Loop iteration counter=" + TOTAL);
		InvokedStatic.doStatic(dummyObj);
		invokedObj.doObject(dummyObj);
		System.gc();

		// Benchmark Normal Invocation (Static)
		if (true) {
			ts = System.currentTimeMillis();
			for (int i = 0; i < TOTAL; i++) {
				InvokedStatic.doStatic(dummyObj);
			}
			log("Normal Static time=", ts);
		}

		// Benchmark Normal Invocation (Object)
		if (true) {
			ts = System.currentTimeMillis();
			for (int i = 0; i < TOTAL; i++) {
				invokedObj.doObject(dummyObj);
			}
			log("Normal Object time=", ts);
		}

		// Benchmark Reflection Invocation (Static)
		if (true) {
			final Class<InvokedStatic> c = InvokedStatic.class;
			final Method ref = c.getMethod("doStatic", Object.class);
			ts = System.currentTimeMillis();
			for (int i = 0; i < TOTAL; i++) {
				ref.invoke(null, dummyObj);
			}
			log("Reflection Static time=", ts);
		}

		// Benchmark Reflection Invocation (Object)
		if (true) {
			final Class<InvokedObject> c = InvokedObject.class;
			final Method ref = c.getMethod("doObject", Object.class);
			ts = System.currentTimeMillis();
			for (int i = 0; i < TOTAL; i++) {
				ref.invoke(invokedObj, dummyObj);
			}
			log("Reflection Object time=", ts);
		}

		log("Static XX=" + InvokedStatic.getXX());
		log("Object XX=" + invokedObj.getXX());
	}

	private static final void log(final String msg, final long ts) {
		System.out.println(msg + (System.currentTimeMillis() - ts) + "ms");
	}
	private static final void log(final String msg) {
		System.out.println(msg);
	}

	public static class InvokedStatic {
		private static long xx = 0;
		public static void doStatic(final Object dummy) {
			xx += dummy.hashCode();
		}
		public static long getXX() {
			return xx;
		}
	}

	public static class InvokedObject {
		private long xx = 0;
		public void doObject(final Object dummy) {
			xx += dummy.hashCode();
		}
		public long getXX() {
			return xx;
		}
	}
}

Otra referencia interesante:
Direct vs. Parent vs. Interface vs. Static calls

2 Respuestas a “Java: El coste de usar Reflexion (Reflect)

  1. Xavi Rigau 2012/09/21 en 15:23

    Me gustaría ver ese mismo experimento en Android… Dicen que la MV Dalvik está tan trasteada que los resultados pueden variar…

    • technobcn 2012/09/21 en 22:28

      Pues los numeros son estos (corriendo en un Android x86 2.3.5, sobre maquina virtual):

      Loop iteration counter=5000000
      Normal Static time=816ms
      Normal Object time=739ms
      Reflection Static time=9295ms
      Reflection Object time=9450ms
      Static XX=-12448268204826696
      Object XX=-12448268204826696

      La reflexion sigue siendo 10veces mas lenta.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: