さて、今回は、Kit Kat(android 4.4)の内部的な部分を見ていくことにしましょう。アンドロイドの開発者向けのサイトによれば、Kit Katは、512メガバイトのマシンでも動作できるようにしてあるという。もっとも、これは、ハードウェア機器メーカー向け(正確にはアンドロイドをターゲットハードウェアにポーティングする技術者向け)のものであって、自宅にある古いマシンにインストールできるという意味ではありません。しかし、最近のアンドロイドのシステムは、メモリ2ギガバイトが普通になってきていて、少ない機種でも1ギガバイト程度はメモリを搭載しています。Android 4.4を採用してこれから作られるシステムでは、メモリ容量などを押さえた安価な製品が登場する可能性もでできました。
まず、Kit Katでは、システム側のソフトウェア全般でメモリフットプリントを減らすように手が入ったようです。また、これまでは、バックグラウンドで動作するプログラム(アンドロイドではサービスと呼んでいます)を起動時に同時に起動していましたが、これを順番に起動するように改良しました。同時に起動すれば、一時的にであっても、メモリが大量に必要になってしまいます。
また、製品を作るメーカーは、アンドロイドを自社ハードウェアに移植する際にいくつかのオプションを利用できるようにしています。それらには、
- Kernel Samepage Mergin(KSM)
- zRAM
- システムが使うデータ領域の調整(JITコードキャッシュなど)
などがあります。KSMは、もともとカーネルが利用するメモリで内容が同じ領域を強制的に同じ物理メモリ領域に割り当てるものです。仮想マシンシステムなどで、同じオペレーティングシステムを複数動作させる場合などに利用すると、ゲストオペレーティングシステム自体を共用出来る部分がかなりあるため、メモリの利用効率が高くなります。しかし、非仮想化システムであっても、同じプログラムが複数起動したり、結果的に内容が同じメモリ(たとえば中身が全部ゼロなど)を扱う複数のプログラムがあるため、メモリの小さなシステムに有効なことがわかっています。ただし、メモリが同じ内容かどうかのチェックが必要なのと、どちらかが書き込みを行った場合、それぞれを別の領域に割り当て直す必要があるなどのオーバーヘッドが存在します。メモリの利用効率を高めることができるかわりにCPU時間を消費するという「交換条件」があります。
zRAMは、圧縮機能を持つRAMディスクです。RAMディスクは、メインメモリの一部を使って外部記憶をエミュレーションする方法です。圧縮機能があるため、そのままメモリを使うよりも効率的に物理メモリを利用できます。Kit Katでは、このzRAMを使って、メモリの一部を外部記憶装置側に追い出すことが可能です。俗に言う「スワップ領域」をRAMディスク上に置くわけです。実際に記憶を行うのめメインメモリなので、アクセス速度は高速で、圧縮解凍のオーバーヘッドがあっても、実際の高速な外部記憶装置と遜色ない速度を出すことが可能です。
メモリを、スワップ領域に追い出すことで、仮想記憶システムでは、より大きなメモリ空間を使えるようになりますが、CPUによる処理時間のオーバーヘッドと、メインメモリの一部を使うというジレンマがあります。
3つめのオプションは、システム側が使うデータ領域のチューニングです。たとえば、JIT(仮想マシンコードなどのプログラムを実行直前にコンパイルして機械語コードに変換して実行すること)機能では、変換された機械語プログラムをキャッシュしておくことで、再度同じプログラムが実行されたときに変換の手間なく高速に実行が可能です。この領域は大きいほど、2回目の実行が高速化される確率が高くなりますが、その分メインメモリを圧迫してしまいます。キャッシュは、一般的に2回目以降のデータなどの利用を高速化しますが、どの程度のメリットがあるかは、システム状態などによって違いがでてきます。
こうしたオプションは、同梱アプリなどを含めて、実機の上でパラメーターを変えつつ、最適なものを探すことになりますが、場合によっては大きな効果を出すことが可能です。なお、ざっとNexus5を見てみたところ、zRAMもKSMも使われている形跡を見いだすことはできませんでした。前述のパラメーターは、メモリが2ギガバイト未満のハードウェアで有効なオプションと考えられます。
ハードウェア関連の変更点
Kit Katの大きな機能追加に「Hardware Sensor batching」(HSB)があります。これは、センサーからのイベントをハードウェアで処理することで、メインCPUをスリープ状態のままとして、センサーからの情報を収集しつつシステムを長時間動作させる技術です。具体的には、加速度センサーなどをこのHSBで処理することで、万歩計アプリなどがバッテリを消費してしまうことがなくなります。これまで、アンドロイドのアプリから加速度センサーを使う場合、イベントが報告される間隔を指定して、アプリが起動される時間間隔を長くすることでバッテリの消費を抑えていました。このため、精度を上げようとすると、バッテリ消費が増えて、あまり実用的ではなかったのです。
センサーによってイベントの発生のタイミングや機能がいろいろとありますが、おそらくは、超低消費電力のプロセッサコアを動かし、センサーからのイベントをこれで処理する方法などがあります。
また、このHSBを使った機能として「Step Detector and Step Counter」があります。これは、ユーザーが歩いたことを検出してその歩数を数える機能です。具体的なアプリケーションとしては「Moves」というアプリが公開されており、これを使うと、歩いた歩数や位置などを記録することができます。
「Hardware Sensor batching」(HSB)により低消費電力でユーザーの歩みを検出できる「Step Detector and Step Counter」機能を利用した万歩計アプリMoves。単に歩数を計るだけでなく、GPSなどで得た地図情報や移動が徒歩なのか、交通機関なのかを区別して記録できる |
このHSBは、ハードウェア依存の機能であるため、既存のハードウェアにKit Katを入れても利用できないと思われますが、今後登場するハードウェアでは、広く採用される可能性があります。というのも、このHSBや関連する機能を利用することで、アプリケーション側も、以前よりも細かく情報が得られ、バッテリが長持ちするためにアプリケーション自体の有用性も高くなるからです(半日しか持たない万歩計を誰が持ち歩くでしょう?)。
もう1つ、Kit Katの開発者向けオプションには、Javaアプリのランタイムを切り替えるオプションがあり、これまで使われてきたDalvik VMからARTへ切り替えることができます。 ARTとは、Android RunTimeの略で、簡単にいうと、Dalvik VM用にコンパイルされた仮想コードのアプリをインストール時に機械語コードに変換して実行します。これに対して従来使われているDalvikは、実行直前に機械語に変換して実行するJITと呼ばれる機能を持っています。どちらも同じように見えますが、JITでは、実行直前にコンパイルする関係で、対象のプログラムを深く調査する時間がありません。このため、生成される機械語コードは実行は高速ですが、必ずしも最適化されているとは限りません。また、一部の仮想コードは、コンパイルせずに実行されることもあります。
これに対してARTの場合、インストール時にコンパイルを行うため、実行するアプリケーションをもう少し詳しく調査する時間を取ることができます。
だったら、なぜ最初から機械語コードにしないのかというと、現状のアンドロイドアプリは、Dalvik仮想マシンの仮想機械語命令で記述されていて、しかも、アンドロイドは、ARMプロセッサ以外にもIntel系プロセッサやMips系プロセッサのものもあるからです。
ARTに切り替えると、システムを変更して再起動したあと、組み込まれているシステムを機械語に変換しはじめます。このため、状態によっては、ユーザーが利用できるようになるためかなり時間がかかります。ほぼ初期状態でも5分以上変換にかかっています。間違っても外出中に切り替えなどしないことをおすすめします。これは、どちらかというと、アプリの開発者がARTでも自分のアプリがARTでも正しく動作するかを確認するためのものです。
開発者オプションにある「ランタイム選択」でDalvikかARTを選択できる |
ARTを選択すると、システムが再起動し、ロックスクリーンが出る前にインストールされているアプリの最適化(コンパイル)が行われる |
バックグラウンドで動作しているアプリの情報には、メモリ利用量や呼び出しているサービスとその実行時間などが表示される |
プロセスの統計情報では、フォアグラウンド、バックグラウンド、キャッシュされているアプリの3つの統計情報を表示可能 |
Dalvik VMは、アンドロイド用に開発された仮想マシンで、標準的なJavaのVMと違って、レジスタアーキテクチャモデルを採用した仮想コードを実行します(標準的なJavaVMの仮想コードはスタックマシンモデル)。
切り替えると、たしかに早くなったように感じるアプリもありますが、Nexus 5は標準状態でも十分速いため、体感的には、「速度改善があるかも」と「そんなの気のせい」の間ぐらいです。Antutuベンチマーク(4.1.1)で計測したところ、900ぐらいしか差がでなかったので、今回標準添付になったQuickOfficeに8メガバイトほどのExcelファイルを読み込ませてみました。すると、読み込み時間に約3倍程度の差が出ました。もちろん、これがすべての場合の速度差ではありません。しかし、このファイルは、現在のPCでも開くときにちょっと間を感じる程度には負荷がかかり、2000年頃のPCでは、数分かかることもありました。それがたった30秒で、しかもスマートフォンで開くようになったのだから、ちょっと驚きです。というよりも、開くことができたこと自体が驚きです。これまで、PC以外では、このファイルを開くことはできませんでした。
Dalvik | ART | 改善比 | |
---|---|---|---|
1回目 | 1分42秒 | 0分35秒 | - |
2回目 | 1分28秒 | 0分32秒 | - |
3回目 | 1分31秒 | 0分33秒 | - |
4回目 | 1分27秒 | 0分35秒 | - |
平均 | 1分32秒 | 0分34秒 | 2.7倍 |
このように負荷が高く、CPUがずっと動くような時間のかかる処理に関していえば、DalvikとARTには、これぐらいの差が出ることが分かりました。もちろん軽い処理ならば、その差がわからないこともあるかもしれせまん。まだ、ARTは正式提供ではなく、これまで使われてきたDalvikと比べると動かないアプリなどがあるかもしれません。しかし、何かその実力の片鱗を見たような気がします。
また、同様に開発者向けオプションですが、プロセス状態の表示でメモリをどのぐらい利用しているかを表示できるようになりました。今後、メモリのあまり大きくないマシンを使うような場合、こうした機能でアプリケーションによるメモリ利用量を調べ、よりメモリ利用量の少ないアプリを使うということも可能でしょう。
本稿は、2013年11月25日にAndorid情報のWeb専門誌「AndroWire」に掲載した記事を再構成したものです。