Macのメモリ解放スクリプト

以前に書いたメモリ解放スクリプトを少し改良しました。

#!/bin/sh

INACTIVE_THRESHOLD=8192
FREE_THRESHOLD=1024

VM_STAT=$(vm_stat)
    FREE=$(echo "$VM_STAT" | awk '/Pages free/ {print $3}' | tr -d '.')
    ACTIVE=$(echo "$VM_STAT" | awk '/Pages active/ {print $3}' | tr -d '.')
    INACTIVE=$(echo "$VM_STAT" | awk '/Pages inactive/ {print $3}' | tr -d '.')
    SPECULATIVE=$(echo "$VM_STAT" | awk '/Pages speculative/ {print $3}' | tr -d '.')
    WIRED=$(echo "$VM_STAT" | awk '/Pages wired down/ {print $4}' | tr -d '.')

INACTIVE=$(expr $INACTIVE / 256)
FREE=$(expr \( $SPECULATIVE + $FREE \) / 256)

if [ $INACTIVE -gt $INACTIVE_THRESHOLD ] || [ $FREE -le $FREE_THRESHOLD ];  then
  #purge
  du -sx / >& /dev/null & sleep 15 && kill $! >/dev/null 2>&1
fi

以前はINACTIVEだけ監視してましたが、空きメモリも監視するようにしました。

これでMacbook Airでも戦えるはず……

サンプルだとINACTIVEが8192MB以上または空きメモリが1024MB以下になるとメモリ解放を試みます。

MacのInactiveメモリを解放する

MacってInactiveに割り当てられたメモリが増えつづけるので、なんか気持ち悪いですよね。
基本的には放っておいて構わないとは思いますが、Inactiveが大きすぎるのも嫌なので、Inactiveが一定以上になったら開放するスクリプトを作ってみました。

#!/bin/sh

THRESHOLD=8192
INACTIVE=`vm_stat |grep inactive |awk '{print $3}' |sed -e "s/¥.//g"`

if [ `expr $INACTIVE / 256` -gt $THRESHOLD ] ; then
  purge
  #du -sx / >& /dev/null & sleep 15 && kill $! >/dev/null 2>&1
fi

このシェルスクリプトをcronで定期実行すると Inactiveが8192MB以上の時にメモリ解放してくれます。

purgeコマンドだと効きが強すぎて重いので、duコマンドを使ったほうが良いかも(効きは弱いですが)

Dummynet続き

DummynetのQoS設定が判らないので試験環境を用意して実際に動作を確認してみました。

試験環境では、QoSの効果を体感しやすくするためにpipeで128kbpsの帯域制限をかけています。
この状態で巨大ファイルを転送しながらsshで操作が可能か確認を行いました。

MASK無し

ipfw pipe 1 config bw 128k
ipfw sched 1 config type WF2Q+
ipfw queue 1 config sched 1
ipfw queue 1 ip from any to any

sshでキー入力を行ってもエコーが秒単位で返ってこない。
QoSは全く機能していない。

FLOW_MASK

ipfw pipe 1 config bw 128k
ipfw sched 1 config type WF2Q+
ipfw queue 1 config sched 1 mask all
ipfw queue 1 ip from any to any

キー入力の応答は即時に返ってくるが、たまに応答の遅れを感じる。

SCHED_MASK

ipfw pipe 1 config bw 128k
ipfw sched 1 config type WF2Q+ mask all
ipfw queue 1 config sched 1
ipfw queue 1 ip from any to any

キー入力の応答は即時に返ってくる。
応答の遅れなどは感じられない。

簡単なテストですが、QoSを動作させるには queueまたはschedでmask設定が必要だと判りました。
そして、schedでmask設定を行った方がより滑らかにQoSが動作しているように感じられました。

<20時57分 追記>
と言う訳で、DummynetでQoS設定を行う場合はschedのSCHED_MASKでトラフィックフローの振り分けを行うのが正解っぽいです。
スケジューリングアルゴリズムをFIFOにしたところ、SCHED_MASKを設定すると想定外の動作となりました。
FIFOならバーストトラフィックに帯域占有されるはずなのですが、WF2Q+と同様にsshのレスポンスが即時に帰ってきてしまいます。
FIFOとは思えない動作なので、想定通りの動作であったFLOW_MASKの設定が正しいようです。

この辺りは余裕が有る時に追試したいと思います。