swapをやめる。swapファイルの置き場所を変える。

MBA使いの同僚にswapの逃し方を聞かれたので調べた。
swapの管理はdynamic_pagerデーモンがやっている。
とりあえず、swapをオンオフにするのは以下のコマンドでできる。
オフ。

$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist 

オン。

$ sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist

変更後は、有効にするには再起動が必要になる。
swapファイルの数が増えると、動作も遅くなるようだ。
一旦作成されると削除されないようなので、メモリ増設をしたりする場合は、一度オフにして起動して、swapファイルを削除、その後、オンにして再起動したほうがよさそう。


止めるとスリープから復帰するときに画面がおかしくなったり、フリーズしたりするというリポートあり。
フリーズはメモリ使い切ってる場合だろうな。
スリープ復帰時の画面の乱れは、復帰直後は、スクリーンショットのダミー表示して速い振りしてるだけだし、それの領域をswapに逃がしているのかも。


swapファイルは、/private/Var/vm/にあるそう。
見てみる。

MacBook:~ kinneko$ ls -lh /private/Var/vm/
total 31457280
-rw------T  1 root  wheel   8.0G  1  8 07:11 sleepimage
-rw-------  1 root  wheel    64M  1  8 07:21 swapfile0
-rw-------  1 root  wheel    64M  1  8 07:21 swapfile1
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile10
-rw-------  1 root  wheel   128M  1  8 07:21 swapfile2
-rw-------  1 root  wheel   256M  1  8 07:21 swapfile3
-rw-------  1 root  wheel   512M  1  8 07:21 swapfile4
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile5
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile6
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile7
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile8
-rw-------  1 root  wheel   1.0G  1  8 07:21 swapfile9

11個もあるじゃないですか... orz
さすが、いつもカツカツでメモリ使ってるだけのことはあるな(^^;。
MacってUNIX系と違って、専用パーティションを生でswapに使うんじゃなくて、あくまでswapもファイルシステム上のファイルになっているというのが面白い。


SSDモデルでは、そもそも容量が少ないのと、頻繁に読み書きすると寿命が短くなる問題から、パフォーマンスや安全性を犠牲にしても、swapは別ボリュームに逃したいということもあるだろう。
swapの置き場所を変更する方法は以下にまとまっている。
Moving the swapfiles to a dedicated partition in Snow Leopard
http://superuser.com/questions/28414/moving-the-swapfiles-to-a-dedicated-partition-in-snow-leopard


dynamic_pagerの設定は以下にある。

/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist

plistファイルはバイナリになっているので、これをエディタで編集できるようにXMLに変換する。

MacBook:~ kinneko$ file com.apple.dynamic_pager.plist 
com.apple.dynamic_pager.plist: Apple binary property list
MacBook:~ kinneko$ sudo plutil -convert xml1 com.apple.dynamic_pager.plist
MacBook:~ kinneko$ file com.apple.dynamic_pager.plist 
com.apple.dynamic_pager.plist: XML  document text

中身は以下。

MacBook:~ kinneko$ cat com.apple.dynamic_pager.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>EnableTransactions</key>
	<true/>
	<key>HopefullyExitsLast</key>
	<true/>
	<key>Label</key>
	<string>com.apple.dynamic_pager</string>
	<key>OnDemand</key>
	<false/>
	<key>ProgramArguments</key>
	<array>
		<string>/sbin/dynamic_pager</string>
		<string>-F</string>
		<string>/private/var/vm/swapfile</string>
	</array>
</dict>
</plist>

ProgramArgumentsのdynamic_pagerのロード部分を使用するボリュームに合わせて変更する。
ファイルシステムは、HFSである必要があるかも。
テスト環境では、SDカードに退避する設定をやってみる。実際に最後まではやらないけどね。
SDは以下。ファイル名合わせだけなので、128MB(!)のゴミSD。
HFS+でフォーマットしておく。

MacBook:~ kinneko$ df | grep Volumes
/dev/disk2s1      248240       7816    240424     4%    /Volumes/SDCard

swapを使う前に事前にマウントしておく必要がある。
mountコマンドでやるのもいいが、Macにはボリュームを自動マウントする機能があるので、それで有効になるのを待つ。
これは、wait4pathコマンドで確認できる。
動きを確認してみる。

MacBook:~ kinneko$ sudo diskutil unmount /Volumes/SDCard/
Volume SDCard on disk2s1 unmounted
MacBook:~ kinneko$ wait4path /Volumes/SDCard/ && echo "mount: /Volumes/SDCard/"
mount: /Volumes/SDCard/

ちゃんと動くようだ。
plistを以下のように編集する。

	<key>ProgramArguments</key>
	<array>
		<string>/bin/bash</string>
		<string>-c</string>
		<string>/bin/wait4path /Volumes/SDCard/ && /sbin/dynamic_pager -F /Volumes/SDCard/swapfile</string>
	</array>

plistをバイナリに戻す。

MacBook:~ kinneko$ sudo plutil -convert binary1 com.apple.dynamic_pager.plist 
MacBook:~ kinneko$ file com.apple.dynamic_pager.plist 
com.apple.dynamic_pager.plist: Apple binary property list

試してないけど、再起動したら反映されるはずだ。