Android NDKを使用してJava言語とC言語で速度比較をする(IO編)
こんにちはBig iguchiです。
早速ですがみなさん、
Androidは画像の読み込みが遅いと思ったことはありませんか?
それ以前に、Androidは大きな画像を読み込むとすぐに落ちると思ったことはありませんか?
今日はそんな問題を解決するための方法を一つ紹介しようと思います。
そうです。Android NDKです。
しつこくてすいません。Javaでも出来ると言う方はご紹介ください。
Android NDKを使用すればJavaのヒープメモリを使用せずCのヒープメモリを使用するため、落ちることやGCによるストップザワールのようなことが発生しないと予測しました。
方法は、1920×1080の画像を読み込みRGBのデータを取得できるところまでの時間を測定します。実機はHT-03Aを使用しました。使用した画像は以下です。

取得してから画像を扱うところのパフォーマンスは画像処理編で試しているので省きます。
ではさっそく試してみましょう。
Javaのコードは以下です。
SDカードから画像を読み込んでBitmapを作成し、getPixelsでpixelのRGBを取得できる箇所までの処理になります。
これだけで終わりです。Javaで書くと簡単ですね。生産性やメンテナンス性がいいことはJavaのいいところです。
C言語は以下です(エントリーポイントになるJava側とC言語側で分けて記述します。)
Java側
SDカードから画像を読み込んでnativeコードのgetImageColor(cpath)に値を渡す処理になります。getImageColor(cpath)の処理は以下のC言語側の処理に続きます。
C言語側
ここでポイントがあります。Javaは自動的に画像を解析しRGBカラーにしてくれますが、本来jpegやpngは圧縮されたバイナリになっているためこれらを解凍しなければなりません。そのために使用するのがlibpng.aやlipjpeg.aというC言語のライブラリになります。
libpngのソースコードはここにあるのですが、これをAndroid用にコンパイルするのは一苦労なので、今回はAndroidOS自体をコンパイルするときに作成されたlibpng.aを使用します。Androidのコンパイル方法はここを参考にしてください。ここで生成されたものはAndroidで使用できます。
使用するライブラリを取り込んだプロジェクト構成は以下のようになります。

プロジェクト構成
libpng.aやらlibjpeg.aなど画像を解凍するC言語ライブラリがたくさん入ってますねヘッダファイルもプロジェクトに入れておきます。
libpng.aの使用方法は以下を参考にしてください。非常に分かりやすかったです。
http://www.kcrt.net/program/uselibpng_read.html
では早速速度比較してみましょう。
結果
Javaは落ちました。
メモリアロケートのところです。せつないです。。。。C言語は最後まで計算してくれました。
この結果を見るだけでもやはりCヒープを使用すれば大きな画像を扱えそうです。
このままでは速度比較できないので画像を
720×480のSDサイズに変更して比較しました。今度はどちらも落ちませんでした。
結果は以下です。
Javaは 1033ms、C言語は 422ms。。
うーんIOのほうは、演算時ほど劇的な速度の向上はないけれどパフォーマンスは上がっているようです。それでも2倍くらいは出てますからね。
すごく厳密に調査した訳ではないけれど、ここまでの結果を考慮するとAndroid NDKを使用すると、メモリリソースを効率よく使用でき、演算時ほど速度の向上ないけれどパフォーマンスは出そうです。
画像読み込みで問題になったときもAndroid NDKを使用する価値はありますね。
今回はしんどかったー。なのでここまで!。
ヨーロッパにいきたい。


