Androidは遅い?javaは遅い?

最近Androidをよく使うことが多いのですが、AndroidにしろiPhoneにしろ、モバイル端末にしてはびっくりするほどぬるぬるですよね。今日はそこで、Androidの計算の処理速度ってどんなもんなんよ?って思って、処理速度を計算するプログラムを書いてみた。

使用したデバイスはGalaxy tab 1GHzです。int long float doubleをそれぞれ100万回計算する処理と、リストを5000回挿入と捜査するプログラムです。ソースは下の方に書いておきました。

結果はというと・・・

あれ・・?遅くね?この結果を参考にすると、intを100万回計算するだけで1秒以上時間がかかるってすごくね?

ていうか、arrayList遅くね?たかだか5000回挿入して、 イテレーターで読み取るだけで0.2秒かかるわけですよwww

おかしくねwww?っていろいろ調整してみた結果ですが・・・

はい、何という不手際でしょうね。端末のケーブルを引っこ抜いて、端末のアイコンから起動してやるとこの驚きの速さですよwwwww

ていうか、デバッガー遅い!!!100倍以上差がついたら、そりゃ遅く感じますねwwwwwwwwちなみに、Androidの処理が遅いときに、プロファイラーを使うと便利ですって記事を書こうと思っていたのですが、ここまでデバッガーを取り付けるだけで処理速度が落ちるんだったら、プロファイラーの値もかなり信用できませんね。ちなみに、androidのプロファイラであるtraceviewを使うときはeclipseでこのボタンを押すと、どのメソッドに時間がかかっているかとかが分かります。1回押すとプロファイリングを開始して、もう一度押すと結果が出ます。inclusiveというのが、そのメソッドを呼ぶのにかかった時間+そのメソッドが呼んだほかのメソッドでかかった合計時間。exclusiveというのがそのメソッド単体でかかった時間です。プログラムの処理のどこにボトルネックがあるのか分かりそうなものですが、実際使ってみると、デバッガーが遅すぎで使い物にならないんでしょうね。

結論としては普通にintやlongがそこそこ早くて、floatやdoubleのような浮動小数の計算は遅いですね-。ってことがわかります。ちなみに、Androidでプログラムを書くときはfloatを使う必要はそれほど無さそうですね。昔のデバイスだとfloatの方が高速とかあったんでしょうが、今では余裕でdoubleを使った方が精度もよくて速度も速いという。

あと、コレクションって処理が遅いかと思ったのですが、そんなに遅くないですね。LinkedListだとイテレーターを使った処理が早くて、ArrayListだとインデックスによるアクセスが早いみたいですね。処理内容が違うので配列と比較するのってどうかと思うのですが、むしろ配列によるインデックスアクセスより、LinkedListの列挙子(イテレーター)によるアクセスの方が早いというのが予想外でした。デバッグ実行中は、コレクションはがくっと速度が落ちるのでデバッグがままならない気もするが・・・。それでも、コレクションは積極的に利用していきたいですね。

ちなみに、同様のintを1o億回計算するプログラムをC#で記述したところ、経過時間は2395ミリ秒(Core2duo 3GHzによる)
はえええええええええええええええええええええwwwwwwww

と一瞬思ったのですが、Androidのjavaの計算速度の8倍しか速くないっておかしくないか?こっちは、galaxy tabの1GHzとcore2duo3GHzで8倍しか開かないって、想像以上にAndroidって高速に処理できるわけですよ。

使ったソース
[java]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ArrayList<String> result = new ArrayList<String>();
//intを100万回加算
long s = System.currentTimeMillis();
int a = 1;
for(int i = 0; i < 1000 * 1000; i++){
a = a + 77;
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//longを100万回加算
s = System.currentTimeMillis();
long b = 1l;
for(int i = 0; i < 1000 * 1000; i++){
b = b +77l;
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//floatを100万回加算
s = System.currentTimeMillis();
float c = 1.0f;
for(int i = 0; i < 1000 * 1000; i++){
c = c +77.7f;
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//doubleを100万回加算
s = System.currentTimeMillis();
double d = 1.0;
for(int i = 0; i < 1000 * 1000; i++){
d = d + 77;
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//ArrayListを5000回addして、イテレーターで読み取る
s = System.currentTimeMillis();
ArrayList<String> l = new ArrayList<String>(5000);
for(int i = 0; i < 5000; i++){
l.add("a");
}
for(String str : l){
//String tmp = l.get(i);
str = "b";
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//LinkedListを5000回addしてイテレーターで読み取る
s = System.currentTimeMillis();
LinkedList<String> n = new LinkedList<String>();
for(int i = 0; i < 5000; i++){
l.add("a");
}
for(String str : n){
str = "b";
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

//配列を5000回書き込んで5000回読み取る
s = System.currentTimeMillis();
String[] array = new String[5000];
for(int i = 0; i < 5000; i++){
array[i] = "a";
}
for(int i = 0;i<array.length;i++){
array[i] = "b";
}
result.add((System.currentTimeMillis() - s)+"ミリ秒");

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
// アイテムを追加します
adapter.add("int :"+result.get(0));
adapter.add("long :"+result.get(1));
adapter.add("float :"+result.get(2));
adapter.add("double:"+result.get(3));
adapter.add("arrayList:"+result.get(4));
adapter.add("LinkedList:"+result.get(5));
adapter.add("配列:"+result.get(6));
ListView listView = (ListView) findViewById(R.id.listView1);
// アダプターを設定します
listView.setAdapter(adapter);
[/java]
[java] Stopwatch st = new Stopwatch();
st.Start();
int a = 0;
for (int i = 0; i < 1000 * 1000 * 1000; i++)
{
a = a + 77;
}
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds);
Console.ReadLine();
[/java]

コメント

  1. ingaouhou より:

    追伸というか修正:AndroidのVMか何かのキャッシュがあるのか、intやlongの計算は2回目の実行だとやたら速くなるという現象があった。(いったんアプリケーションを終了させるともとの速度に戻る)どういうことだろ・・・結局Androidは早いのか・・・?Javaは早いのは間違いないけど・・・Javaの速度の一因はJITの優秀さとも聞くが、AndroidのJITは優秀なのやら・・・結局よく分からん・・・よく分からん・・・

  2. aoi_nagatsuki より:

     traceviewを使うときにケーブル引っこ抜いとけばいいような?
     Debug.startMethodTracing()とか使えばプログラム内でトリガできるのでデバッグ実行しておく必要ないとおもいます。
     一通り実行したら後はSDに保存されたプロファイル結果をtraceviewに放り込んで解析。

     ちなみに二回目以降が早くなるのはむしろ「一回目はJITでネイティブコードにコンパイルするのが遅い」らしいです。

タイトルとURLをコピーしました