Androidとリフレクション(HT-03A編)

ちょっと無茶かなと思いながらも、先日のテストをdocomo HT-03A/HTC Magic(Android 1.6)でも実行してみることにした。
しかし、そのままのコードでは一つのテストタスクが終了する前にANR※となってしまい計測にならないので、テストロジックを別スレッドで実行し、結果を文字列で戻すようにコードを変更することにした。

  • ReflectionTest (別スレッド版)
    new Thread(new Runnable() {
        @Override
        public void run() {
            Task tasks = new Task {
                    new MethodCallTask(),
                    new FieldCallTask(),
                    new ReflectionTask(),
                    new ReflectionTaskWithSearchSetter()
                    new ReflectionFieldTask(),
                    new ReflectionFieldTaskWithSearchField(),
                };
            try {
                Measure measure = new Measure();
                measure.setCount( 100000 ); // 1タスクを10万回実行する。
                measure.run( tasks );
                final String result = measure.result.toString(); 
                ReflectionTest.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        txt.setText(result);
                    }
                });
            } catch ( Throwable e ) {
                e.printStackTrace();
            }
        }
    }).start();

#必殺のRunnable二重実装。この辺もっと見通しよく実装できるようになればなぁ。Javaじゃ無理だなぁ。

  • 実行結果

コードが変更になったため、念のためEmulator、Nexus oneでも追試を実施している。

タスク HT-03A Emulator Nexus one JavaSE6
メソッド呼び出し 150 msec 243msec 37msec 1msec未満
フィールドアクセス 114msec 300msec 27msec 1msec未満
リフレクション-メソッド(検索時間を含まず) 3540msec 2395msec 488msec 43msec
リフレクション-メソッド(検索時間を含む ) 11597msec 7823msec 2000msec 193msec
リフレクション-フィールド(検索時間を含まず) 1065msec 790msec 164msec 67msec
リフレクション-フィールド(検索時間を含む ) 6492msec 3097msec 703msec 202msec
実行環境 ・HT-03A/HTC Magic CPU Qualcomm® MSM7201a 528 MHz MEM 192MB OS Android 1.6 build DRD08 ・Nexus one CPU Qualcomm® QSD8250 1GHz MEM 512MB OS Android 2.2 build FRF91 ・JavaSE6/Emulator CPU Intel® Xeon X5450 3.0Ghz (×2) MEM 4GB OS Windows® Vista with service pack 2/Android SDK 2.2 FRF91 Java JavaSE1.6 build 1.6.0_20-b02

コードを変えた影響はあるようで全ての環境において若干だが結果が変わっている。UIスレッド外で処理を行うようにしたため実行スレッドの優先度が下がることによる影響だろうか。エミュレータはスレッドの切替えには特に弱く、如実に影響が出ている。

結論として、やはりHT-03Aには荷が重かった。リフレクションを使用した結果はPC上で動かしたエミュレータにも劣っており、最も重いテスト(リフレクション-メソッド-検索時間含む)での経過時間は1万msecを超えてしまっている。これではちょっと厳しいだろう。

  • ここまでのAndroidのリフレクション戦略
    • 1Ghzのプロセッサと500MB以上のRAMが使えるのであればリフレクションは十分に実用になる
    • Androidにおけるリフレクションの実装ではメソッドよりもフィールドアクセスの方が性能が格段に良い
    • HT-03A(528mhz/192MB)とNexus one(1Ghz/512MB)では同じ設計/実装をしてはいけない(どうしてもそうしなければならないならばHT-03A側に合わせる)

Javaがそうだったようにパフォーマンス戦略は1年も経てば違うものになっている可能性があるため、努々これが鉄則などとは思わないことだ。
逆に「まず計測してみるべし」というのはどんなプラットホームでも鉄則だ。

※Application Not Responding. Androidがアプリケーションの無反応を検出してすることをいい、SDKと同じコードであればUIスレッドで5秒の遅延はANRと判断される。