I/O MultiplexingでAndroidのための効率のよい画像ローダをつくる検証

モバイルアプリのスレッドプールサイズの最適化(画像読み込み編) - クックパッド開発者ブログ

これに対する「I/O多重化すればスレッド数とか気にしなくていいんじゃないの」という意見を聞いて、それもそうだなと思ったので検証してみました。

前提知識

  • IO多重化にはjava.nio.channels.Selectorjava.nio.channels.SocketChannel を使う
  • Selector は Perlの IO::Select によく似たインターフェイスと機能を持つ
    • つまり select(2) ないし同等のシステムコールへのインターフェイス
    • Androidの場合に使われるのは epool(2) かも
  • SocketChannelSelector で多重化できるsocket
  • Androidのdocumentはあまりないが、Oracleのドキュメントがあるので参考になる
  • Oracle JDK7にはNIO.2というものがあってより多重化をやりやすいらしいけど、Androidにはないので関係ない

結果

とりあえず最低限HTTP 1.0で複数の画像のURLをリクエストしてレスポンスをパースしてviewに表示させるところまではできました。response headerのパースを真面目にやってないので、このままプロダクションで使うのは無理ですが、とりあえず検証はできるのでこれでよしとします。サポートしているプロトコルは HTTP/1.0 だけで、HTTPSは扱えません。

実機*1で検証したところと、シリアルにリクエストを送る場合は1000msくらいかかるところ、IO多重化したほうは300msくらいで済みます。この実装だと1つのスレッドを専有するうえにプライオリティも考慮しませんが、実験的なコードとしては十分でしょう。

というわけで、AndroidでもIO多重化は有効だとわかりました。最強の画像ローダを実装する場合は、画像のロードはIO多重化してシングルスレッドで行い、デコードはCPUの数だけスレッドを作って行うのが理想的だと思われます。

*1:Xperia Z4 / Android 5.0.2 / LTE