[go: up one dir, main page]

[この記事は Andrew Hayden、Google Play ソフトウェア エンジニアによる Android Developers Blog の記事 "Saving Data: Reducing the size of App Updates by 65%" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

Android ユーザーは、Google Play で数百億のアプリやゲームをダウンロードしています。また、デベロッパーは頻繁にアプリをアップデートして、ユーザーにすばらしいコンテンツを提供したり、セキュリティを改善したり、ユーザー エクスペリエンス全般を向上させたりしています。こういったアップデートでは、多くのデータをダウンロードする必要があります。しかしユーザーは、端末で消費したデータ量を気にしています。Google は今年、bsdiff アルゴリズム(Colin Percival 氏が開発)の利用開始を発表しました。bsdiff の利用によって、アプリの完全な APK のサイズと比べると、アップデートのサイズを平均 47% 減らすことができました。

本日(*原文公開当時)は、さらにアップデートのサイズを削減する新たなアプローチをお知らせします。それは、ファイルごとのパッチ適用です。ファイルごとのパッチ適用によるアプリのアップデートでは、完全なアプリよりも平均 65% 小さくなり、場合によっては 90% 以上小さくなることもあります。

以前のアプローチと比較すると、なんと 1 日あたり最大 6 ペタバイトのユーザーデータを節約できることになります。

この方法では、アプリの新しいバージョンを入手する際に、Google Play から端末にアプリの旧版と新版との 差分 を記述したパッチが送信されます。

たとえば、まもなく出版される本の著者が 1 文だけ変更したいとします。全文を送り直すよりも、編集者にその変更内容を伝える方がはるかに簡単です。同じように、パッチを使うと APK 全体をダウンロードするよりもはるかにサイズが小さくなり、ダウンロード時間も短縮されます。

ファイルごとのパッチ適用で使われるテクニック

Android アプリは APK としてパッケージ化されています。APK は、特殊なルールに基づいた ZIP ファイルです。ZIP ファイル(と APK)の中にあるほとんどのコンテンツは、Deflate と呼ばれるテクノロジーを使って圧縮されています。Deflate はデータの圧縮には優れていますが、元の(圧縮されていない)コンテンツの変更点を特定するのが非常に難しくなるという欠点もあります。元のコンテンツをわずかに変更しただけでも(本の中の 1 語だけ変更するように)、Deflate が出力する圧縮データは まったく異なるものに見える場合があります。 元の コンテンツの差分を作るのは簡単でも、 圧縮された コンテンツの差分を作るのはとても難しいため、パッチは非効率になってしまいます。

左側の圧縮されていないテキストを 1 文字変更しただけで、右側の圧縮されたテキストがどのくらい変わるかをご覧ください。

そのため、ファイルごとのパッチは、圧縮されていないデータで検出された差分に基づきます。パッチの生成にあたって、まず古いファイルと新しいファイルの両方を解凍し、差分を計算します(ここでは、まだ bsdiff を利用しています)。次に、パッチを適用するため、古いファイルを解凍して圧縮されていないコンテンツに差分を適用し、新しいファイルを再圧縮します。その際に、端末上の APK が Play Store 上の APK とバイト単位で完全に一致していることを確認する必要があります(この理由については、APK 署名スキーマ v2 をご覧ください)。

新しいファイルの再圧縮には、2 つの問題があります。1 つ目の問題は、Deflate の設定によって Deflate の出力が色々と変わることです。そもそも、圧縮の際にどのような設定が使われたのかはわかりません。2 つ目は、Deflate には多くのバージョンが存在しており、ユーザーの端末上にある Deflate が適切なバージョンか確認する必要があります。

幸運にも、Play Store のアプリを分析したところ、Play Store のほぼすべての Deflate コンテンツで、zlib(もっとも普及している Deflate ライブラリ)に基づいた、互換性がある最近のバージョンの Deflate が使われていることがわかりました。さらに、実質的に使われている設定は、デフォルト(level=6)と最大(level=9)の圧縮設定だけでした。

以上のことを踏まえると、元々の Deflate 設定を検出して再現できると言えます。つまり、データを解凍し、パッチを適用してデータを再圧縮し、元々アップロードされたものと まったく同じバイト列 を作ることができます。

ただしこの方式には、端末側で必要な処理能力が高くなるという欠点もあります。最近(たとえば、2015 年以降)の端末では、再圧縮には 1 メガバイトあたり 1 秒少しかかり、古い端末や能力が低い端末はさらに時間がかかります。現時点の分析によると、平均で、パッチのサイズが半分になるとパッチの適用(再圧縮を含めたファイルごとのパッチ適用)にかかる時間は倍になります。

今のところ、この新しいパッチ テクノロジーの利用は自動アップデートのみに制限しています。これは通常、夜間にスマートフォンが電源に接続され、ユーザーが使用していない可能性が高いときにバックグラウンドで行われるアップデートです。これによって、ユーザーが手動でアプリをアップデートする際に、いつもより長く待たなければならないという事態を回避しています。

ファイルごとのパッチ適用の効率性

以下に、すでにファイルごとのパッチ適用を使っているアプリのアップデートの例を示します。

アプリ
元のサイズ
以前の(bsdiff)パッチサイズ
(元のサイズに対する割合)
ファイルごとのパッチによるサイズ(元のサイズに対する割合)
71.1 MB
13.4 MB(-81%)
8.0 MB(-89%)
32.7 MB
17.5 MB(-46%)
9.6 MB(-71%)
17.8 MB
7.6 MB(-57%)
7.3 MB(-59%)
18.9 MB
17.2 MB(-9%)
13.1 MB(-31%)
52.4 MB
19.1 MB(-64%)
8.4 MB(-84%)
16.2 MB
7.7 MB(-52%)
1.2 MB(-92%)


免責事項: 現在、ファイルごとのパッチはバックグラウンドでのみ利用されており、インタラクティブなアップデートには利用されていないため、手動で「アップデート」を押した際に表示されるパッチサイズとは異なる場合があります。

データを節約してユーザー(そしてデベロッパー)をハッピーに

以上の変更は、10 億人以上の Android ユーザー コミュニティが、最小限のデータ量でアプリの定期アップデートを行えるように設計されています。一番の長所は、デベロッパーは何もする必要がないことです。このアップデートのサイズ削減は、無償で行われます。

技術的な詳細など、ファイルごとのパッチ適用についてさらに詳しく知りたい方は、Archive Patcher GitHub プロジェクトをご覧ください。ソースコードを含む情報を閲覧できます。ファイルごとのパッチ適用は、完全なオープンソースです。

APK サイズをさらに削減したいデベロッパーの方は、APK サイズ削減のための一般的な推奨事項もご覧ください。


Posted by Khanh LeViet - Developer Relations Team

[この記事は Anthony Morris、Google Play ソフトウェア エンジニアによる Android Developers Blog の記事 "Improvements for smaller app downloads on Google Play" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]

Google Play は急成長を続けており、昨年、Android ユーザーは Google Play Store から 650 億のアプリをインストールしています。また、新しい魅力的なコンテンツの配信、セキュリティ脆弱性のパッチ、ユーザーのフィードバックへのすばやい対応など、デベロッパーは今まで以上に頻繁にアプリをアップデートしています。

しかし、多くのユーザーは使用するデータ量に敏感です。Wi-Fi を使用していない場合には特にです。Google Play は、アプリのインストールやアップデートの際に転送する必要があるデータを削減しつつ、ユーザーに対するデータのコストを透過的にするという改善に投資しています。

本記事では、アップデートの仕組みや APK のサイズを最適化する方法についてのヒントを紹介します。

アプリのアップデートのサイズを減少させる新たな差分アルゴリズム

Play Store の約 98% のアプリのアップデートは、ダウンロードした APK ファイルの変更(差分)と既存のファイルへのマージであるため、アップデートのサイズを減らすことができます。先日、差分アルゴリズムの bsdiff (*1) が導入されました。これは、以前のアルゴリズムと比べて最大 50% 以上のパッチを削減することができます。bsdiff は、ネイティブ ライブラリの効率的な差分を生成することに特化しており、バージョン間でコンパイル済ネイティブ コードが変わるような特別な手法を活用しています。効率を上げるため、ネイティブ ライブラリは未圧縮の状態で格納します(圧縮すると、差分アルゴリズムに悪影響を与えます)。

Chrome の例:
パッチの説明 以前のパッチサイズ bsdiff のサイズ
M46 から M47 へのメジャー アップデート 22.8 MB 12.9 MB
M47 マイナー アップデート 15.3 MB 3.6 MB

未圧縮のネイティブ ライブラリがないアプリのサイズは、以前の差分アルゴリズムに比べて平均 5% 減少します。

APK 拡張ファイルに差分アルゴリズムを適用し、さらにアップデート サイズを削減する

APK 拡張ファイルを使うと、サイズが 2 GB までの大きなファイル(高解像度グラフィック、メディア ファイルなど)をアプリに追加できます。これはゲームなどでよく使われます。APK に加え、APK 拡張ファイルに適用する差分アルゴリズムと圧縮アルゴリズムも拡張されています。これによって、平均で初回インストール時には 12%、アップデート時には 65% のダウンロード サイズを削減できます。

Play Store のサイズ情報の明確化

ダウンロード サイズの削減と合わせて、Play Store の使用データ量やダウンロード サイズの情報を明確に表示するような改善も行われています。Play Store には、APK のファイルサイズではなく、実際のダウンロード サイズが表示されます。既にアプリをインストールしている場合は、アップデート サイズのみが表示されます。この変更は現在公開されています。



*1: Colin Percival, Naive differences of executable code, http://www.daemonology.net/bsdiff/, 2003. 

例 1: APK の新しい「ダウンロード サイズ」の表示


例 2: APK の新しい「アップデート サイズ」の表示


ダウンロード サイズを減らすためのヒント

1. 正しいサイズ計測のための最適化: ユーザーは、ダウンロード サイズ(アプリのインストールやアップデートでどのくらいのバイトが転送されるか)やディスクサイズ(アプリがどのくらいのディスクを使用するか)を気にしています。このどちらもが元の APK ファイルサイズと同じではなく、相関性があるとも限らないことを知っておくことが重要です。


Chrome の例:
圧縮済みのネイティブ ライブラリ 未圧縮のネイティブ ライブラリ
APK サイズ 39 MB 52 MB(+25%)
ダウンロード サイズ(インストール) 29 MB 29 MB(変更なし)
ダウンロード サイズ(アップデート) 29 MB 21 MB(-29%)
ディスクサイズ 71 MB 52 MB(-26%)


Chrome では、APK のネイティブ ライブラリを圧縮していないので初回ダウンロード サイズは同じですが、Google Play ではダウンロード用の圧縮が既に行われているため、APK のサイズは増加しています。未圧縮ファイルでは差分の効率が上がっているためアップデート サイズが減少し、圧縮済みネイティブ ライブラリをコピーする必要がなくなっているためディスクサイズも減少しています。

2. APK サイズの減少: 使用されていないリソースやコードなど、不要なデータを APK から削除します。

3. APK の構成要素のサイズを減らすことによる最適化: たとえば、JPEG ではなく WebP を使用するなど効率的なファイル形式を使ったり、未使用コードを削除するために Proguard を使用したりします。
APK サイズの削減についての詳細情報はこちらをご覧ください。また、I/O 2016 セッション「アプリをダイエットする」を見て、Wojtek Kaliciński がどのように APK サイズを削減しているかを学ぶこともできます

Posted by Yoshifumi Yamaguchi - Developer Relations Team