ReflectionでMethod実行するとどの位遅いのか

とある処理を汎用化する場合にReflectionを使いたくなる場面がありますが、どの程度の速度劣化があるか把握する必要があります。

通常のWebアプリだとその他の要素(HTTP通信、DBやら)でReflectionが槍玉に挙げられる事は少ないと思いますが、それなりに速度が求められるシステムの場合、Reflectionを使うのは歩みを止めて考える必要があります。

では、計測コードです。

package test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestMain {
	private static final int LOOP_MAIN = 1_000_000;
	private static final int LOOP = 1_000;

	public static Method method;

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		TestMain main = new TestMain();

		// 通常のMethod実行
		long t0 = System.nanoTime();
		for (int ii = 0; ii < LOOP_MAIN; ii++) {
			main.execGet();
		}
		System.out.println("通常のMethod実行:" + (System.nanoTime() - t0) / LOOP_MAIN);

		// Reflectionを利用したMethod実行
		t0 = System.nanoTime();
		for (int ii = 0; ii < LOOP_MAIN; ii++) {
			main.execReflection();
		}
		System.out.println("Reflectionを利用したMethod実行:" + (System.nanoTime() - t0) / LOOP_MAIN);
	}

	public TestMain() {
		try {
			method = TestEntity.class.getMethod("getVal1");
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

	public void execGet() {
		TestEntity testEntity = new TestEntity();
		for (int ii = 0; ii < LOOP; ii++) {
			testEntity.getVal1();
		}
	}

	public void execReflection() throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		TestEntity testEntity = new TestEntity();

		for (int ii = 0; ii < LOOP; ii++) {
			method.invoke(testEntity);
		}
	}
}

package test;

public class TestEntity {
	private int val1;

	public int getVal1() {
		return val1;
	}

	public void setVal1(int val1) {
		this.val1 = val1;
	}
}

■環境
Core2Duo 2.93GHz
Windows7
・jdk1.7.0_05


■結果
 通常のMethod実行 :7 ns
 Reflectionを利用したMethod実行 :4,533 ns
 ※千回のMethod実行を100万回繰り返した。
 ※結果は千回実行あたりの時間です。
 ※GCはゼロ回です。


Method実行については、まぁ話にならないですね。
ReflectionのMethod実行も1回あたり4ns程度なのでnanoを争うシステムでなければ十分に速いです。
usec勝負のレベルだと使用は控える感じで、画面表示まで1秒以内とかのWebアプリであれば恐れることなく使ってOKという結果。

通常のMethod呼び出しは速いですね。

※2012/6/28 getMethod()をexecReflection()で毎回コールしていたのはフェアじゃないので、TestMainのコンストラクタで事前取得する様に変更。結果はほぼ変わり無しでしたが。
※2012/7/1 Reflectionも結構速いという結果に修正