とは言えPCなどのように後からメモリを増設するわけにも行かないので、工夫で何とかしなければなりません。そのためにAndroidには(Linuxにはと表現する方が正しいのかな?)SwapとCompcacheという2つの仕組みが提供されています。
設定するためには、一部を除きコマンドレベルでの対応が必要です。そのため、Cyanogenmodでシステム起動時に実行されるユーザスクリプトであるuserinit.sh (/sd-ext/userinit.sh) に実行すべきコマンドを記述して設定するようにしています。(Compcacheについてはスペアパーツからでも設定可能ですが、ここから設定するとサイズ24MB固定&userinit.shの設定内容が反映されなくなりますのでご注意下さい)
SwapとCompcacheの組み合わせで、以下の4つの設定が可能です。
1.Swap Only
Swap(Linux swap)のみ設定します。使用する領域はファイルでもパーティションでも可能ですが、私はSDカードの第3パーティション(/dev/block/mmcblk0p3)に256MBのswapパーティションを作成しました。
userinit.shに記述する内容は以下の通りです。
swapon /dev/block/mmcblk0p3
swap領域のサイズは用意したパーティションのサイズで決まります。(なのでコマンドにはサイズは書きません) パーティションサイズはあとで変更するのが大変なのでご注意下さい。
2.Compcache Only
Compcacheのみ設定します。
このCompcacheってのが最初全然理解できなくて、メモリからあぶれたデータを書き出す先が何でメモリ上にあるんだ…と頭を抱えていたんですが、これって昔流行ったRAMダブラー的な何かなんですね。補助記憶にデータを書き出すコストよりもCPUでデータを圧縮するコストの方が低いので、メモリの一部をデータ圧縮付きのswap扱いにして、メモリ上に置けるデータ量を増やすと。確かに実メモリの少ない携帯とか組み込み向けにはいいのかもしれません。
設定可能なサイズは16MB〜48MBくらいです。これはシステム的な制約ではなく、実用上このくらいが妥当でしょう、と私が思っている値です。twitterにて
とりあえずサイズは推奨値っぽい24MBとしました。
userinit.shに記述する内容は以下の通りです。
modprobe ramzswap
rzscontrol /dev/block/ramzswap0 --disksize_kb=24480 --init
swapon /dev/block/ramzswap0
rzscontrol /dev/block/ramzswap0 --disksize_kb=24480 --init
swapon /dev/block/ramzswap0
swapと違いサイズ変え放題です。と言っても再起動は必要ですが。(やって出来なくはないのですが、システム不安定になるのでお勧めできないです)
3.Compcache with Swap
CompcacheとSwapを同時に設定します。Compcacheはswapのバッファ領域的に扱われるため、システムから見えるswapのサイズはswapパーティションの大きさになります。
Compcacheとして設定可能なサイズはCompcacheのみの時と同じと考えていいと思います。サイズはサンプルとして書かれていた値をそのまま採用し16MBとしました。
userinit.shに記述する内容は以下の通りです。
modprobe ramzswap
rzscontrol /dev/block/ramzswap0 --backing_swap=/dev/block/mmcblk0p3 --memlimit_kb=14688 --init
swapon /dev/block/ramzswap0
rzscontrol /dev/block/ramzswap0 --backing_swap=/dev/block/mmcblk0p3 --memlimit_kb=14688 --init
swapon /dev/block/ramzswap0
4.Compcache and Swap
CompcacheとSwapを同時に設定します。先ほどの3との違いは、Compcacheもswapパーティションも同じswap領域と見なす事。そのためシステムから見えるswapのサイズはCompcacheの大きさ+swapパーティションの大きさになります。
swapにはパーティションごとに優先度があるため、優先度の高い方から使用され、満杯になると次に優先度の高いパーティションが使われます。ただ、その優先度設定のオプションであるpri=xxをどうやって設定したらいいのか分かりません…。(fstabに書く方法なら分かったのですが、Compcacheはfstabには定義できないので)
とりあえずCompcacheを24MBとし、Compcacheとswapの優先度は特に意識せずに設定してみました。
userinit.shに記述する内容は以下の通りです。
modprobe ramzswap
rzscontrol /dev/block/ramzswap0 --disksize_kb=24480 --init
swapon /dev/block/ramzswap0
swapon /dev/block/mmcblk0p3
rzscontrol /dev/block/ramzswap0 --disksize_kb=24480 --init
swapon /dev/block/ramzswap0
swapon /dev/block/mmcblk0p3
以上4つのパターンで、Compcacheのサイズを変えながら色々試してみた結果、個人的には以下の結論に達しました。
・CompcacheとSwapは併用しない。使うならどちらか。
・個々の操作のレスポンスを求めるならCompcache。
サイズは24MB〜32MB程度にとどめておく。
・マルチタスキングを重視するならswap。
サイズは思いっきり大きくする。推奨256MB。
で、私はどんな設定にしているかというと、今はCompcache 24MBです。swap使った方が使いかけのアプリを落とされる可能性が減って本来のマルチタスク的な使い方はしやすいのですが、やはりCompcacheとのレスポンスの差は大きいです。特にカメラ系のアプリはswapだと数十秒レベルで起動を待たされるのに、Compcacheだとものの2〜3秒で起動します。カメラはよく使う機能だけに、この差は大きすぎ。
ただちょっと気になっているのが、Compcacheのみで運用するようになってから、突然の再起動(操作中ではなく、放置している間に突然発生する)が起こるようになった事。これがCompcache弊害なのか、test5以降に潜むバグなのか、それ以外の何か(例えばOCとか)が原因なのかはっきりとは分かっていません。とりあえずCompcacheが48MBと32MBでは発生したので、今は24MBで様子見をしているところです。(サイズの問題なのかも全然分かっていないのですが)
ここに来てだいぶ安定してきたCyanogenmod 5.0.7ですが、やはり唯一の電話として使うにはまだまだ安心できない安定度だと思います。これはCyanogenmodの問題と言うよりも、Android自身の抱えている問題なのかもしれませんが。なのでこれ1台での運用は激しく非推奨。通話とメール用には1台安定して使える携帯を持っておき、PocketWifiやb-mobileSIMなどを使って「趣味としての」「携帯っぽい形をした何かw」として使う事をお勧めしたいです。
twitterにて色々と教えて下さったり、人柱として頑張って下さっている皆様に感謝!
これからもよろしくお願いします。私もまだまだ頑張りますよ!
Twitter / Search - #ht03a
http://twitter.com/#search?q=%23ht03a
Twitter / Search - #cm5
http://twitter.com/#search?q=%23cm5
Userinit.sh - CyanogenMod Wiki
http://wiki.cyanogenmod.com/index.php/Userinit.sh
Linuxのスワップ処理を最適化するためのヒント - SourceForge.JP
http://sourceforge.jp/magazine/07/12/05/0057203
/sd-ext/userinit.shに
modprobe ramzswap
rzscontrol /dev/block/ramzswap0 --disksize_kb=32640 --init
swapon /dev/block/ramzswap0
を追記してrebootしてみたのですがfreeで確認したらどうやら適応されていないみたいです。
CM5.0.7に入ってるスペアパーツの圧縮キャッシュにチェックをON・OFFなど試してみましたがダメでした。何か手順に問題がありますでしょうか?
cyanogenさんのwikiの設定方法に
sysctl -w vm.swappiness=30;
ってのが最後にあったのですがあれは必要ないってことでOKでしょうか?
またお手すきの時にわかればお教えください。
スペアパーツの圧縮キャッシュのチェックを外し
vi /sd-ext/userinit.shに下記項目を追記したら有効になりました。
modprobe ramzswap;
rzscontrol /dev/block/ramzswap0 --disksize_kb=32640 --init;
swapon /dev/block/ramzswap0;
sysctl -w vm.swappiness=30;
bash-4.1# compcache stats
DiskSize: 32640 kB
NumReads: 22501
NumWrites: 20150
FailedReads: 0
FailedWrites: 0
InvalidIO: 0
NotifyFree: 15108
ZeroPages: 1612
GoodCompress: 78 %
NoCompress: 7 %
PagesStored: 3472
PagesUsed: 1553
OrigDataSize: 13888 kB
ComprDataSize: 4937 kB
MemUsedTotal: 6212 kB
userinit.shよりもスペアパーツの設定の方が早く動いてしまうため、userinit.sh上の設定は有効にならないんですかね。スペアパーツ側をOFFにしておくのは記事の中に追加させていただきます。
compcache statsコマンドは知りませんでした。
サイズを変えた時の妥当性を知るにはよい情報ですね。
ありがとうございます!
とりあたまさんのハイレベルなブログ、
理解はできてませんがいつも参考にさせて頂いています。
さて、この間CM5の安定版が出た折に、
設定のためにCyanogenModのWikiのCompcacheのページを見てて「?」と思いました。
とりあたまさんの方では
「3.Compcache with Swap
Compcacheはswapのバッファ領域的に扱われるため〜」
とありますが、
Cyanogen Wikiの方では
「Compcache + 支援Swap
Compcacheが、最初に使われます。
一旦Compacheがいっぱいであるならば、伝統的なSwapが使われます。」
と書いてあるのです。
userinit.shに記述してる内容は同じものだと、
素人目には見えるのですが。
(大きな勘違いかもしれません。ごめんなさい)
もし、気が向くようでしたら一度検証していただけると嬉しく存じます。
CyanogenMod Wikiの問題のページですが、
このコメント欄のホームページアドレスのページに
Web翻訳しておきました。
良かったら使って下さい。
失礼しました
私が試してみた限り、3の「Compcache with Swap」の場合はfreeで確認できるswap容量にCompcache分が含まれませんでした。(--backing_swapで指定したswapパーティションのサイズと同じになりました)
Compcache plus Backing Swap(このblog内の表現だとCompcache with Swap)については、翻訳していただいたページに途中で1度だけ出てくる「Swap支援compcache」という表現(翻訳)が一番しっくりくると思っています。あくまでもメインはswapで、compcacheはそれを支援するためにある。ページアウト=即swapへの書き出しとせず、まずはメモリ上のcompcacheに書き出す。すぐにページインされる時はSDへの書き出しが発生しないのでIOコストが抑えられる。そんな事が狙いなのではないかと。
ただ実際には同一ページに関するページアウト→ページインが間隔を開けずに発生する事は希だと思うので、compcacheに書き出されたデータはほとんどがswapパーティションにも書かれてしまう。そうするとcompcacheでの圧縮にかかるCPUコストの分linux swapのみよりもパフォーマンスが落ちてしまうので、推奨設定として扱われていないのではないかと予想しています。
全て私の予想なので、実際は全然違うのかもしれないのですが…。
compcacheのコードが理解できるくらいのスキルがあるといいんですけどね。
tomo様のコメント内容を無い頭で頑張って咀嚼しました。
要するに、CM Wikiもtomo様も表現は違えど同じことだったのですね。
アプリAを起動する
↓
Homeアプリのデータが非アクティブになる
↓
アプリAのデータが増大し、残メモリがしきい値に達する
↓
HomeアプリのデータをCompcacheへ移動してメモリを空ける
↓
アプリBを起動する
↓
アプリAのデータが非アクティブになる
↓
アプリBのデータが増大し、残メモリがしきい値に達する
↓
アプリAのデータがCompcacheへ移動し、残Compcacheがしきい値に達する
↓
HomeアプリのデータをLinux Swapへ書出し、Compcacheを空ける
と、「ところてん形式」と想像します。(ザックリですが)
で、BがKillされると、Aがメモリに戻り、CompcacheにHomeデータがバックグラウンドで書き戻されるので問題ない。
しかし、B起動中にHomeボタンを押すとSDから書き戻しながら解凍しながらで最悪。
全然違ってるかもしれませんが、今ひとつ釈然としなかったものがスッキリしました。ありがとうございます。