はてブロ@ama_ch

https://twitter.com/ama_ch

Dropboxのメモリ消費量があまりにも鬼畜だったので監視して適宜殺すことにした

一応前回のエントリーGrowlで監視プロセスを通知してみよう - テックノート@ama-chからの続き。
Dropboxがいつの間にか落ちていてもGrowlさんが通知してくれるようになりすっかり安心した僕は、卒論も書かず元気に面白い動画を求めてニコニコ動画をさまよっていたのでした。
「・・・ん、なんか再生がもたつくな?」
何となくActivity Monitorを開いて見たら、そこには驚くべき光景が広がっていました。



ちょおおおおい!1.84GBっておま!!!
ぐぐってみたらどんなに食ってる人でも100MBとかだったのに、この数値は一体なんなんだ!どうりでいきなりファンが高速回転を始めたり、何もしてないのにメモリの空きが10MBになったりしてたわけですね\(^o^)/


これはどうにかしないと非常にマズイ!
とりあえずダウンロードページからアプリケーションをダウンロードし直してみる。バージョンはおそらく0.6.384から0.6.402に上がった。でもメモリ使用量に目立った改善なし。起動してすぐに100MB超えました。うおおあー
「なぜ重くなるのか」という根本的な部分がわからないから、対症療法で頑張るしかない><
Dropboxは起動してないと困るけど、メモリ1GBとか食ってたら一旦終了して欲しい。起動してない時はGrowlで通知するようにしたから、今度は起動中にメモリ欲張り出したら殺す処理を考えよう。


メモリの消費量を調べるといってまず思いつくのはtopコマンドだけど、これは変数に入れてどうこうできそうにない><
グーグル先生によると、どうやら"ps aux"でメモリの消費量も出るらしい。どれどれ・・・

18:40 ama-ch% ps aux -m |head -1; ps aux -m |grep Dropbox.app |grep -v grep                                                                                                    [~]
USER       PID %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
ama-ch     167   0.2 45.6  3136996 1914132   ??  S     2:51PM  26:28.98 /Applications/Dropbox.app/Contents/MacOS/Dropbox -psn_0_143395

おぉ。RSSという項目がメモリの消費量(KB)だそうな。%MEMはメモリの消費量をパーセントで示したものだそうです。45.6%てちょwww
1914132KB≒1.8GBだから、なるほど確かに半分弱食ってるなぁ。それじゃあこのコマンド結果のRSSの部分を判定して、ある値を超えたらkillしちゃえばいいんじゃね!


そんで、前回も踏まえて考えたのがこれ。

#!/opt/local/bin/zsh

# コマンドの実行結果を単語ごとに配列へ格納
set -A array $(ps aux -m |grep Dropbox.app |grep -v grep)
if [ $(echo $array |wc -w) -eq 0 ];
then    # 配列が空だったら警告
    /usr/local/bin/growlnotify -t 'Warning' -m 'DropBox is dead!!' -I /Applications/Dropbox.app
else    # 起動中にメモリ消費量が1GB(1048576KB)を超えてたらkill
    test $array[6] -gt 1048576 && kill $array[2] && /usr/local/bin/growlnotify -t 'Report' -m 'DropBox was killed.' -I /Applications/Dropbox.app
fi

crontabにこう書いて使う

*  *  *  *  * /Users/ama-ch/scripts/check_dropbox.zsh


はぁはぁ、zshで配列を扱う方法が絶望的に分からなかった・・・色々調べたおかげでシェルスクリプトの勉強になりました。 zshだと配列の添字は1からなんだ!
簡単に解説すると、

  1. "ps aux -m |grep Dropbox.app |grep -v grep"の実行結果を単語ごとに配列へ格納
  2. 配列が単語を1つも含まない≒空っぽだったら、「Dropbox落ちてるよ!」とGrowl通知
  3. 空っぽじゃなかったら、メモリ消費量を見てそれが1GBを超えていればkill&そのことをGrowlで報告

という処理を毎分おこないます。
ワンライナーにして直接crontabに記述したら、やっぱり動かなかった>< なんかcronがコマンドを実行する環境?って、普段自分が使ってるのと違う気がする。今度ちゃんと調べたい。


こんなもんでとりあえずどうだろう。あんまり頻繁にkillしちゃうようだとかえって面倒なことになりそうだなー、1日に数回以内でおさまってくれれば良いんだけど。今のところ起動して1時間くらいで150MB程度でおさまってる。
あとなんで「open -a Dropbox」だとちゃんと起動しないのかが気になるなー。

追記

公式wikiの機能要求リストに

Some memory usage optimizations (particularly on OS X)

FeatureRequests - Dropbox Wiki

と書かれてた。OS Xでのメモリ消費は最適化が不十分ということなのかな?
更にフォーラムではOS Xユーザーで常時700MB〜800MB食ってるというユーザーが。

Sorry... but I have to laugh... Granted I'm on OS X so it's not directly comparable, but I'm currently at 500MB RAM usage and it tends to go up to 700-800MB

Using ~50Mb of RAM « Dropbox Forums

うーん、Dropboxがメモリ食いまくるのは仕様なのかなー。バージョンアップに期待しとこう。

更に追記(2/9)

AppleScriptを使ったらコマンドラインでDropboxを起動することができました。これでDropboxを全自動監視&再起動できる!!
まず、スクリプトエディタで以下の内容を記述します。

tell application "Dropbox" to run

アホみたいにシンプルですね!適当にrunDropbox.scptとか名前をつけて保存します。
あとは、先述のGrowlで警告を出していたところにこいつを実行する行を追加すればおk。

#!/opt/local/bin/zsh

# コマンドの実行結果を単語ごとに配列へ格納
set -A array $(ps aux -m |grep Dropbox.app |grep -v grep)
if [ $(echo $array |wc -w) -eq 0 ];
then    # 配列が空だったら警告
    /usr/local/bin/growlnotify -t 'Warning' -m 'DropBox is dead!!' -I /Applications/Dropbox.app
    osascript ~/applescripts/runDropbox.scpt    # この行を追加
else    # 起動中にメモリ消費量が500MBを超えてたらkill
    test $array[6] -gt 512000 && kill $array[2] && /usr/local/bin/growlnotify -t 'Report' -m 'DropBox was killed.' -I /Applications/Dropbox.app
fi

これで、Dropboxを全自動で起動できます。せっかくなのでついでにkillするメモリ消費量の基準は500MBと強気に設定してみました!
更に余談で、

% osascript -e applescript

と叩くと、applescriptの部分に記述したAppleScriptが実行できるらしい。1行のスクリプトをわざわざファイルに保存するのは面倒なので、こりゃいいやと思って意気揚々と

% osascript -e "tell application \"Dropbox\" to run" 

と叩いたら、"open -a Dropbox"と打った時と同じようにすぐ落ちてしまいました。なんでじゃー><