読者です 読者をやめる 読者になる 読者になる

sendBroadcast()のコスト

android

極端な話、普通のメソッド呼び出しとどの程度違うのか、と気になったので試してみた。

package com.komamitsu.bench;

import java.util.concurrent.Executors;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;

public class BenchActivity extends Activity {
  private static final String ACTION_HOGE = "hogehoge";
  private static final int LOOP_COUNT = 10000;

  private volatile int countForIntent;

  private final BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      // Log.d("#####", "intent onReceive");
      countForIntent++;
    }
  };

  private volatile int countForThread;

  void onRecieveFromThread(String label) {
    countForThread++;
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    findViewById(R.id.intent).setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        Executors.newSingleThreadExecutor().execute(new Runnable() {
          @Override
          public void run() {
            IntentFilter intentFilter = new IntentFilter(ACTION_HOGE);
            registerReceiver(receiver, intentFilter);
            Intent intent = new Intent(ACTION_HOGE);
            intent.putExtra("hoge", "hogehoge");

            long start = System.currentTimeMillis();
            Log.d("#####", "intent start: count=" + countForIntent);
            for (int i = 0; i < LOOP_COUNT; i++) {
              sendBroadcast(intent);
            }

            long end = System.currentTimeMillis();
            Log.d("#####", "intent end: count=" + countForIntent + ", time=" + (end - start));
            unregisterReceiver(receiver);
          }
        });
      }
    });

    findViewById(R.id.methodcall).setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        Executors.newSingleThreadExecutor().execute(new Runnable() {
          @Override
          public void run() {
            long start = System.currentTimeMillis();
            Log.d("#####", "methodcall start: count=" + countForThread);
            for (int i = 0; i < LOOP_COUNT; i++) {
              onRecieveFromThread("hogehoge");
            }

            long end = System.currentTimeMillis();
            Log.d("#####", "methodcall end: count=" + countForThread + ", time=" + (end - start));
          }
        });
      }
    });
  }
}

こんな感じで、10000回、メソッド呼び出しをしたり、ブロードキャストインテントを投げたりして時間を計ってみた。

結果、

09-19 01:22:08.264 D/#####   (16201): intent start: count=0
09-19 01:22:22.984 D/#####   (16201): intent end: count=10000, time=14728
09-19 01:22:25.325 D/#####   (16201): methodcall start: count=0
09-19 01:22:25.335 D/#####   (16201): methodcall end: count=10000, time=3

メソッド呼び出しはまぁ置いといて、ブロードキャストインテントを投げると一回辺り1.5msec近くかかる。

vmstat見てたら、freeが減ってanonが増えてた. swap outが必要な領域が増えたぽい。