ページ

2015年3月20日金曜日

[Xamarin] おぉ!Xamarin は Objective-C や Java より高速だったのか!

(タイトルは釣り用の誇張表現w)

@atsushieno さんのツイートより。

ほう、これは興味深い。
Mobile App Performance Redux」にて iPad Air 2(iOS 8.2)と Moto X(Android 5.0)で同じ意味のコードの速さ比べをやってみたという結果が紹介されています。
速度比べしているのは 600点の GPS 座標のデータ(これ自体は事前に準備)をごにょごにょと計算しながら SessionManager という独自のクラスに格納していくという内容みたいです。これを 1,000回繰り返した時間の 10回の平均なようです。

へ~ぇ、iOS では Swift > Xamarin > Objective-C だったとのこと(Swift が一番高速で次が Xamarin)。Swift と Objective-C ってこんなに速度違うってことにびっくり。そしてなにより Xamarin が Objective-C より速いとは。
ちなみに Xamarin.iOS ではビルド時にネイティブコードにコンパイルします。本家 .NET のようにコンパイル時に中間言語(IL)を作って実行時にそれをアセンブルして動くっていう形ではありません。iOS では実行時にマシンコードを生成するという方法は禁止されている(アプリの審査が通らない)のでこういった方式にはできません。なので、コンパイル時にネイティブコードが生成されます。
※ このあたりが知りたい方は @atsushieno さんの「Xamarin.iOSの仕組みとアプリケーションの構成」とかを読むといいんじゃないかと思います。
というような仕組みなので、ライブラリがきちんと最適化されていてコンパイラが賢ければそれだけ速くなってもまったくおかしくありません。というか、Xcode の Objective-C コンパイラってろくに最適化とかしてないってことなんですかね?

続いて Android。こちらも数値的には Xamarin の方が Java より速いです。が、まぁ、これはほぼ同じと言っていい感じですね。
ちなみに、Xamarin.Android は本家 .NET と同じ仕組みです。コンパイル時には IL が生成されて実行時に mono ランタイムによって解釈されて動きます。また、mono ランタイムは Java ランタイムの上に乗っているのではなく Android OS の上に乗っています。Java ランタイムと横並びになってるわけです。この辺りの話は「Xamarin.Androidの仕組みと、ソフトウェア構成」とかを読むといいんじゃないかと。

ちょっと気になったところ
コメント的に書いてあるところですが、Swift 版で最初は class Point を作って class Gate: Point と Point を継承するって形にしていましたがこれはパフォーマンス的にまずいので、struct Point にして Gate は Point を継承しない形にしたそうです。(Swift はまったく詳しくないのでわかってませんが、.NET の値型・参照型と同じ話なのかな?) たぶん これ とか これ の話じゃないかと思います。
Xamarin 版では、ループの中で DateTime.UtcNow を使ってたのはパフォーマンス上の制限になるので外に追い出したそうです。修正した結果は これ かな?元ネタを探してみたら このやりとり のようです。どうも DateTime.UtcNow はまずローカルタイムを取得してからそれを UTC に変換するので意外と処理量が多いってことなようです。まじですか。びっくりです。

パフォーマンスなんてどんな処理内容かによってガラッと変わったりしますからすべてがこうなるなんてまったく言えないと思いますが、それでもこの記事の内容は、たまに聞く「Xamarin って余計な層が噛んでるからネイティブに比べたら遅いんじゃないの?」というほとんど誤解といっていい指摘には十分な反証となりそうです。

0 件のコメント:

コメントを投稿