Android
 Computer >> コンピューター >  >> トラブルシューティング >> Android

Android最適化の神話を暴く――スワップ・Seeder・LMK調整は本当に効果があるのか

Androidのパフォーマンス向上や全体的な最適化をテーマにした解説記事は世の中に数多く存在します。その中には確かな情報もあれば、理論上だけの話、あるいはすでに古くなったAndroidシステムの運用方法に基づくもの、さらには完全なデタラメまで含まれています。スワップの推奨、build.propへの値の追加、Linuxカーネルの変数変更などがその典型例です。

さらに、「オールインワン最適化スクリプト」と呼ばれるフラッシュ可能な.zipファイルも大量に出回っており、大幅な性能向上やバッテリー持ちの改善などを謳っています。一部のチューニングは実際に機能することもありますが、大多数は単なるプラセボ効果か、最悪の場合、端末に悪影響を及ぼします。

とはいえ、開発者たちが悪意を持ってスクリプトを公開しているわけではありません。Playストアには確かに怪しい有料アプリも存在しますが、Androidフォーラムで公開される最適化スクリプトは概ね善意によるものです。ただ、開発者自身が誤った情報を信じていたり、さまざまなチューニングを実験しているだけというケースが多いのです。

残念ながら、特に「オールインワン」系スクリプトでは雪だるま式に問題が膨らみがちです。少数のチューニングは何らかの効果を持つ一方、同じスクリプト内の別のチューニングはまったく無意味であるにもかかわらず、実際に何が効いて何が効かないのかの検証もないまま、「魔法の弾丸」として受け継がれていくのです。

こうして多くのオールインワン最適化スクリプトは同じ手法を使い回しており、その一部は完全に時代遅れか、長期的には有害です。要するに、大半のオールインワン最適化スクリプトは、なぜ・どのようにその最適化が「機能する」のかの明確な理解もないまま、おすすめ設定を寄せ集めただけの代物なのです。ユーザーはそれをフラッシュして「動作が速くなった」と主張しますが、実際には、端末を再起動しただけでRAM内のすべてがクリアされ、性能が向上したように感じられただけである可能性が高いのです。

本記事では、Androidのパフォーマンス「最適化」としてよく勧められる定番の手法を取り上げ、それらが単なる神話なのか、それとも正当なチューニングなのかを検証していきます。

スワップ(Swap)――Androidでは不要どころか有害

神話リストの筆頭に挙げられるのがAndroidにおけるスワップです。「最適化」として考えられていること自体がかなり馬鹿げています。スワップの主目的はページングファイルを作成・接続し、メモリ上のストレージ領域を解放することです。紙の上では理にかなっているように聞こえますが、これは対話性がほとんどないサーバー向けの話です。

Androidスマートフォンで日常的にスワップを使用すると、キャッシュからデータがこぼれ落ちることに起因する深刻なラグが発生します。例えば、あるアプリがグラフィックを表示しようとしたとき、そのデータがスワップに追いやられており、別のアプリとのデータ入れ替えでディスクを再読み込みしなければならない状況を想像してみてください。実に混沌としています。

最適化愛好家の中には「スワップでも問題は起きなかった」と言う人もいますが、性能向上をもたらしているのはスワップではなく、Androidに組み込まれたlowmemorykillerの仕組みです。LMKは、使用されていない肥大化したプロセスを定期的に強制終了します。LMKは低メモリ状態への対処のために特別に設計されており、kswapdプロセスから呼び出され、一般的にユーザー空間のプロセスを終了させます。これはOOMキラー(out-of-memory killer)とは異なるものですが、その話題はまた別の機会に。

要点はこうです。例えば1GBのRAMを搭載した端末では、スワップによって必要な性能水準に到達することは決してできません。つまり、Androidにスワップはまったく必要なく、導入すればラグまみれになり、最適化どころか性能の劣化を招くのです。

zRAM――古い端末専用のもので現代では非効率

zRAMは、特定の条件下でのみ有効な端末最適化手法です。対象となるのは古い端末、具体的にはKitKat世代でRAMが512MB程度しか搭載されていない端末です。そんな中、今なお最適化スクリプトにzRAMのチューニングを含めたり、現代的な最適化手法としてzRAMを勧めたりするのは、最新の運用プロトコルに追随していない好例と言えます。

zRAMは本来、MTKチップセットと512MB RAMを組み合わせたような、エントリークラスの低価格マルチコアSoC向けに設計されたものであり、端的に言えば超低価格の中国スマホ向け技術です。zRAMが行うのは、圧縮ストリームを介してカーネルのメモリを分離することです。

シングルコアの旧式端末でzRAMを使うと、推奨されている場合であっても大量のラグが発生しがちです。同様のことが、同一のメモリページを統合して空き容量を作るKSM(Kernel Samepage Merging)技術でも起こります。これはGoogle自身が推奨している技術ですが、常時稼働するカーネルスレッドが重複ページを探してメモリを走査し続けるため、旧式端末ではかえってラグが増加します。皮肉なことに、最適化チューニングを試みることが端末をさらに遅くしてしまうのです。

Seeder――Android 3.0以降は時代遅れ

Android開発者の間で最も議論を呼ぶ最適化ネタの一つがSeederです。この件で反論してみたいという人がいるかもしれませんが、まずはSeederの歴史を確認する必要があります。

Android最適化の神話を暴く――スワップ・Seeder・LMK調整は本当に効果があるのか

確かに、かなり古いAndroid端末に導入したところ動作が改善したという報告は大量にあります。しかし、なぜかそれを現代のAndroid端末にも当てはまる最適化だと信じる人がいますが、それは完全にナンセンスです。Seederが今なお「現代的な」ラグ軽減ツールとして維持・提供されているのは誤情報の一例ですが、これはSeeder開発者の責任ではありません。開発者自身もPlayストアのページで、Android 4.0以降ではSeederの効果は低下すると明記しています。それでもなぜか、現代のAndroidシステムに関する最適化の議論にSeederが登場し続けているのです。

Android 3.0時代のSeederが解決していたのは、Androidランタイムがエントロピー取得のために/dev/random/ファイルを積極的に使用するというバグでした。/dev/random/のバッファが不安定になり、必要なデータ量が満たされるまでシステムがブロックされていました。端末の各種センサーやボタンといった細かい処理がこれに該当します。

Seederの作者は、LinuxデーモンのrngdをAndroid向けにコンパイルし、より高速で予測可能な/dev/urandom経由からランダムデータを取得して毎秒/dev/random/にマージすることで、/dev/random/が枯渇しないようにしました。その結果、エントロピー不足に陥らないAndroidシステムが実現し、動作は格段に滑らかになったのです。

GoogleはAndroid 3.0以降でこのバグを修正しました。それにもかかわらず、なぜかSeederは今もAndroidのパフォーマンス最適化の「おすすめチューニング」リストに名を連ねています。さらに、Seederと同等の機能を持つsEFixのような類似アプリもあり、同じrngdや代替のhavegedを使ったり、/dev/urandomと/dev/randomの間にシンボリックリンクを張ったりしています。現代のAndroidシステムにとって、これは完全に無意味です。

無意味な理由はこうです。新しいAndroidバージョンでは、/dev/random/を使用する主要コンポーネントは3つしかありません。libcrypto(SSL接続の暗号化、SSH鍵の生成など)、WEP/WPA鍵を生成するwpa_supplicant/hostapd、そしてEXT2/EXT3/EXT4ファイルシステム作成時にIDを生成するいくつかのライブラリです。

つまり、現代のAndroid最適化スクリプトにSeederやSeederベースの強化機能を組み込むと、結果として端末の性能が劣化します。rngdが端末を絶えず起こしてCPUクロックを引き上げるため、当然ながらバッテリー消費にも悪影響を与えるからです。

ODEX――自前生成はプラセボ効果

Android端末のストックファームウェアはほぼ常にODEX化されています。これは、/system/app/や/system/priv-app/にあるAPK形式の標準的なAndroidアプリパッケージに加えて、同名の.odex拡張子ファイルが存在することを意味します。odexファイルには、バリデータと最適化仮想マシンを通過済みの最適化されたバイトコードが格納されており、dexoptのようなツールを使って別ファイルとして記録されています。

odexファイルは仮想マシンの負荷を軽減し、ODEX化されたアプリの起動を高速化するために存在します。一方で欠点もあり、ODEXファイルはファームウェアの改変を妨げ、アップデート時に問題を引き起こします。このため、LineageOSなど多くのカスタムROMはODEXなしで配布されています。

ODEXファイルの生成はOdexer Toolなど複数の方法で行えますが、問題はそれが純粋なプラセボ効果だということです。現代のAndroidシステムは/systemディレクトリ内にodexファイルを見つけられない場合、システムが自動的にそれらを生成して/system/dalvik-cache/ディレクトリに配置します。新しいAndroidバージョンをフラッシュした際に「アプリを最適化しています」というメッセージがしばらく表示されるのは、まさにこの処理が行われているからです。

Lowmemorykiller(LMK)の調整――現代では無意味

Androidのマルチタスクは他のモバイルOSとは異なり、アプリがバックグラウンドで静かに動作し続ける古典的なモデルに基づいています。バックグラウンドアプリの数に制限はなく(開発者向けオプションで制限を設定することは可能ですが、一般的には推奨されません)、バックグラウンド実行への移行機能も停止されません。ただし、システムは低メモリ状況においてバックグラウンドアプリを強制終了する権利を保持しています(本ガイドの前半で触れたlowmemorykillerとOOMキラーの話を参照してください)。

lowmemorykillerの仕組みに戻ると、Androidは限られたメモリ量とスワップパーティションがない状態でも動作を続けられます。ユーザーはアプリを起動し続け、切り替えることができ、システムはアクティブなタスクのためにメモリを確保しようと、未使用のバックグラウンドアプリを静かに終了させるのです。

これはAndroidの初期には非常に有用でしたが、なぜかタスクキラーアプリの形で人気を博すようになりました。タスクキラーアプリは一般に害の方が大きいのですが、一定間隔で起動するかユーザーが手動で実行し、大量のRAMを解放したように見せます。「空きRAMが多い=速い端末」という図式ですね。しかしAndroidの場合、そう単純ではありません。

実際には、大量の空きRAMがあることは端末の性能とバッテリー持ちにとってむしろ有害です。アプリがAndroidのRAMに保持されていれば、呼び出しや起動がはるかに容易になります。アプリはすでにメモリ上に存在するため、システムは切り替えに大きなリソースを割く必要がないからです。

こうした理由から、タスクキラーはかつてほど人気がなくなりましたが、Android初心者は依然として頼りがちです(残念ながら情報不足ゆえに)。そして新たなトレンドとして台頭してきたのが、lowmemorykillerメカニズムのチューニングです。例えばMinFreeManagerのようなアプリで、主眼はシステムがバックグラウンドアプリの強制終了を始める前に、RAMの余剰分を増やすことにあります。

標準設定では、空きメモリが約40MBを下回ると、メモリに読み込まれているものの実行されていないアプリが終了されます。

つまり、Androidは常に最低40MBの利用可能メモリを確保し、lowmemorykillerがクリーンアップを開始する前に、もう1つのアプリを受け入れられる余裕を持っています。これは、Androidがユーザー体験を損なわない範囲で最大限にRAMを使おうと常に努めていることを意味します。

悲しいことに、一部の素人愛好家は、LMKが発動する前に例えば100MBの空きを確保するよう値を引き上げることを推奨し始めました。これによりユーザーは実際にRAMを失うことになります(100 − 40 = 60MB)。バックグラウンドアプリの保持に使えたはずの領域を、システムは何の目的もなく空いたまま確保し続けるのです。

LMKのチューニングは512MB RAMの非常に古い端末なら有用であり得ますが、今どきそんな端末を所有している人はいないでしょう。現代の「ローエンド」は2GB、4GB RAM端末ですらミドルレンジと見なされる時代です。LMKチューニングは完全に時代遅れで無用の長物なのです。

I/Oチューニング――意味のないコマンドの数々

Androidの最適化スクリプトには、I/Oサブシステムに触れるチューニングがよく含まれています。例としてThunderBolt!スクリプトを見てみましょう。以下のような行が含まれています。

echo 0 > $i/queue/rotational;

echo 1024 > $i/queue/nr_requests;

最初の行はI/Oスケジューラに対しSSDとして扱うよう指示し、2行目はI/Oキューの最大サイズを128から1024へ引き上げます。$i変数には/sys内のブロックデバイスツリーへのパスが入っており、スクリプトはループで実行されます。

続いてCFQスケジューラに関連する行があります。

echo 1 > $i/queue/iosched/back_seek_penalty;

echo 1 > $i/queue/iosched/low_latency;

echo 1 > $i/queue/iosched/slice_idle;

その後、他のスケジューラに属する行が続きますが、結局のところ、最初の2つのコマンドは無意味です。理由は以下の通りです。

  • 現代のLinuxカーネルは、デフォルトで扱っているストレージ媒体の種類を自動的に判別できます。
  • 長い入出力キュー(1024など)は現代のAndroid端末では役に立ちません。デスクトップPCでも無意味で、本当に推奨されるのは高負荷サーバーだけです。あなたのスマホは高負荷Linuxサーバーではないのです。

Android端末では、入出力で優先されるアプリケーションが事実上存在せず、机械ドライブも搭載されていないため、最良のスケジューラはnoop/FIFOキューです。つまり、この種のスケジューラ「チューニング」はI/Oサブシステムに対して特別なことも意味のあることも何もしていません。実際、あの多岐にわたるコマンド群は、次のようなシンプルなループで置き換えられます。

for i in /sys/block/mmc*; do

echo noop > $i/queue/scheduler

echo 0 > $i/queue/iostats

done

これにより、すべてのドライブでnoopスケジューラが有効になり、I/O統計の蓄積が停止されます。性能への影響はプラスに働きますが、ごくわずかで、ほぼ無視できるレベルです。

性能系スクリプトによく見られるもう一つの無意味なI/Oチューニングが、SDカードのリードアヘッド(先読み)値を2MBまで引き上げるものです。リードアヘッド機構は、アプリがデータへのアクセスを要求する前に媒体からデータを先読みするためのものです。カーネルは将来必要になるデータを予測してRAMに事前ロードし、応答時間を短縮する狙いです。紙の上では素晴らしく聞こえますが、リードアヘッドのアルゴリズムは往々にして外れます。その結果、まったく不要な入出力操作が発生し、高いRAM消費も招きます。

1〜8MBという高いリードアヘッド値が推奨されるのはRAIDアレイです。Android端末では、デフォルト値の128KBのままにしておくのが最善です。

仮想メモリ管理システムのチューニング

もう一つのよくある「最適化」手法が、仮想メモリ管理サブシステムの調整です。通常、対象になるのはvm.dirty_background_ratioとvm.dirty_ratioという2つのカーネル変数だけで、「ダーティ」データを保存するバッファのサイズを調整します。ダーティデータとは、書き込み操作が開始されたものの、まだメモリ上に残ってディスクへの書き込み待ちをしているデータのことです。

LinuxディストロやAndroidでVM管理サブシステムに施される典型的なチューニング値は次のようなものです。

vm.dirty_background_ratio = 10

vm.dirty_ratio = 20

これは、ダーティデータのバッファが総RAM容量の10%に達したときにpdflushスレッドを起こしてディスクへの書き込みを開始するという挙動を意図しています。ディスクへの記録操作が過度に集中した場合、バッファは成長を続け、利用可能RAMの20%に達すると、システムは同期モードでの書き込みに切り替わります。つまり、事前バッファなしで動作するため、データがディスクに書き込まれるまでアプリの書き込み処理がブロックされます(いわゆる「ラグ」です)。

知っておくべきは、たとえバッファサイズが10%に達しなくても、システムは30秒後に自動的にpdflushを起動するという点です。10/20の組み合わせはかなり妥当で、例えば1GB RAMの端末なら100/200MBに相当し、アプリのインストールやPCからのファイルコピーなど、速度がシステムNANDメモリやSDカードの書き込み速度を下回るバースト書き込みの観点では十分すぎるほどです。

なぜかスクリプト作者たちは、この値をさらに absurd な水準まで押し上げようとします。例えばXplix最適化スクリプトでは、50/90という値が見つかります。

sysctl -w vm.dirty_background_ratio=50

sysctl -w vm.dirty_ratio=90

1GBメモリの端末では、これはダーティバッファの上限を500/900MBに設定することを意味します。Android端末にとっては完全に無意味で、ディスクへの常時書き込みが続く状況でしか機能しません。そんなことは高負荷Linuxサーバーでしか起こらないのです。

ThunderBolt!スクリプトはより妥当な値を使っていますが、全体としてはやはりあまり意味がありません。

if [ "$mem" -lt 524288 ];then

sysctl -w vm.dirty_background_ratio=15;

sysctl -w vm.dirty_ratio=30;

elif [ "$mem" -lt 1049776 ];then

sysctl -w vm.dirty_background_ratio=10;

sysctl -w vm.dirty_ratio=20;

else

sysctl -w vm.dirty_background_ratio=5;

sysctl -w vm.dirty_ratio=10;

fi;

最初のコマンド群は512MB RAMのスマホで、次は1GB、それ以外は1GB超の端末で実行されます。しかし実際には、デフォルト設定を変更する理由は一つしかありません。内部ストレージやメモリカードが非常に遅い端末の場合です。その場合にのみ、変数の値を広げる、つまり次のような設定にするのが合理的です。

sysctl -w vm.dirty_background_ratio=10

sysctl -w vm.dirty_ratio=60

こうすると、バースト書き込み時に同期モードへ切り替わることなくディスクへの記録が続けられ、書き込み時のアプリのラグを軽減できます。

その他の無意味なチューニングとパフォーマンス調整

実際には何もしない「最適化」は他にもたくさんあります。その大部分はまったく効果がなく、一部は性能のある側面を改善する一方で、別の面で端末を劣化させます(大抵は性能とバッテリー消費のトレードオフに帰着します)。

以下は、Androidシステムや端末によって有用かもしれないし無用かもしれない、追加の人気「最適化」です。

  • オーバークロック(加速)――性能を少し向上させる。アンダーボルティング――バッテリーを少し節約する。
  • データベース最適化――理論上は端末性能の改善が期待できるが、疑わしい。
  • Zipalign――皮肉なことに、APKファイル内のコンテンツ配置を整えるAndroid SDKの組み込み機能があるにもかかわらず、ストアではzipalignを通していないソフトが多数見つかる。
  • 不要なシステムサービスの無効化、未使用のシステムアプリや使わないサードパーティ製アプリの削除。要するに、ブロートウェアのアンインストール。
  • 特定端末向けに最適化されたカスタムカーネル(繰り返しますが、すべてのカーネルが同じように優れているわけではありません)。
  • 前述のI/Oスケジューラnoop。
  • TCP Westwood輻輳制御アルゴリズム――無線ネットワークではAndroidデフォルトのCubicよりも効率的に使える。カスタムカーネルで利用可能。

無意味なbuild.prop設定

XDA DevelopersフォーラムのLaraCraft304が調査を行い、「専門家」たちが使い方を推奨する/system/build.prop設定のうち、驚くほど多くの項目がAOSPやCyanogenModのソースに存在しないことを突き止めました。以下がそのリストです。

ro.ril.disable.power.collapse

ro.mot.eri.losalert.delay

ro.config.hw_fast_dormancy

ro.config.hw_power_saving

windowsmgr.max_events_per_sec

persist.cust.tel.eons

ro.max.fling_velocity

ro.min.fling_velocity

ro.kernel.checkjni

dalvik.vm.verify-bytecode

debug.performance.tuning

video.accelerate.hw

ro.media.dec.jpeg.memcap

ro.config.nocheckin

profiler.force_disable_ulog

profiler.force_disable_err_rpt

ersist.sys.shutdown.mode

ro.HOME_APP_ADJ

  1. PST?EML?今すぐ知っておきたい代表的なメールファイル形式5選

    1970年代にMIT(マサチューセッツ工科大学)のラボ内でコンピューター間の簡単なやり取りとして始まった電子メールは、21世紀のインターネットにおいて最も普及したコミュニケーション手段の一つへと発展しました。 メールを使えば、テキストや画像、リンクなどを組み合わせて、一人または複数の受信者に送受信できます。公教育や文化的な浸透によって、これは多くの現代のビジネスパーソンにとって常識となっていますが、その細部まで理解している人は実は多くありません。 その一つが「メールファイルには複数の種類がある」という点です。意外と知られていませんが、メールファイルは単一の形式ではありません。この記事では、現在

  2. スマホが止まらない!?Androidで絶対ハマる中毒性抜群のプラットフォームゲームおすすめ4選

    何事への没頭も度を越せば危険で、命に関わることさえあります。しかし楽観的に考えれば、何かに夢中になることは、その分野で頂点に立つきっかけにもなり得るのです。 ゲームへの依存も同じことが言えます。本気でハマれば、人生の浮き沈みをリアルに味わうことになるでしょう。実際、多くの熱狂的なゲーマーが今やプロのeスポーツ選手やストリーマーとして収入を得ています。それは彼らの情熱と、まぎれもなく「依存」のおかげなのです。 ゲームと依存性について語るとき、この2つがいかに相性抜群かは言うまでもありません。家庭用ゲーム機には、『スーパーマリオ』『アドベンチャーアイランド』『コントラ』『ソニック』といった伝説的タ