モバイルアプリのスレッドプールサイズの最適化(画像読み込み編) - クックパッド開発者ブログ
これに対する「I/O多重化すればスレッド数とか気にしなくていいんじゃないの」という意見を聞いて、それもそうだなと思ったので検証してみました。
前提知識
- IO多重化には
java.nio.channels.Selector
とjava.nio.channels.SocketChannel
を使う Selector
は Perlの IO::Select によく似たインターフェイスと機能を持つ- つまり
select(2)
ないし同等のシステムコールへのインターフェイス - Androidの場合に使われるのは epool(2) かも
- つまり
SocketChannel
はSelector
で多重化できるsocket- Androidのdocumentはあまりないが、Oracleのドキュメントがあるので参考になる
- Oracle JDK7にはNIO.2というものがあってより多重化をやりやすいらしいけど、Androidにはないので関係ない
- N preview1 にもなさそう
- AsynchronousSocketChannel は使いやすそうなのに残念
結果
とりあえず最低限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