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も結構速いという結果に修正
- 作者:ジャック シラジ
- メディア: 単行本