« 民意ってなんだっけ | メイン | 勇者ピョグェヌクチャモン »

空きメモリ確保AppleScript「Freemem Keeper」作った

- MacOSX

<また追記>
Snow Leopardに対応しました。
</また追記>

<追記>
今ごろLeopard対応しました。('08/8/20)
</追記>

<更に追記('08 Sep)>
アイコンを作っていただきました。 こちらのページのものも、アイコン付きのものに変更しました。
</更に追記>

先日残り空きメモリ監視AppleScript「Freemem Monitor」作成 (うむらうす) というエントリーを書いた。

空きメモリを周期的に監視し、空きが設定値以下になったらプロンプトを出して、 不使用のメモリを解放するスクリプトを走らせるというものだ。 これにより空きメモリ不足でスワップファイルが増殖して、 OSXの動作がもっさりするのを未然に防ぐのが狙いだ。

すると「なんで自動的にメモリ解放スクリプトを走らせないの?」 という至極もっともな指摘をいただいたた。 そこで、空きメモリ監視スクリプト「Freemem Monitor」と不使用メモリ解放スクリプト「Release Memory」を一体化したスクリプトを作成した。 とりあえず名前は「Freemem Keeper」とする。

Tiger用
ダウンロード:Freemem_Keeper.zip
ダウンロード:Freemem_Keeper(Growl).zip

Leopard用
Freemem_Keeper_wakaba_Small.pngwakabaさんアイコンver
Freemem_Set_for_Leopard(wakaba).zip

解凍すると「Freemem Keeper」というファイルまたは「Freemem Keeper(Growl)」、あるいは「Freemem Keeper for Leopard」、「Freemem Keeper for Leopard(Growl)」というファイルができるはず(拡張子は.app)。 (Growl)は、メモリ解放スクリプトの起動時、終了時の通知をGrowlで行うVersionで、 機能は全く同じ。 AppleScriptとGrowlの連携についてはこちらを参考にした。
AppleScript Support for Growl

<追記>
Freemem_Keeper(Growl)はメモリ値設定のエラーチェックなど文法的な指摘も取り入れ。
いじったものの、実はもはやTigerで動作確認ができない。何かおかしかったらコメント欄までお願いします。
</追記>

使い方はFreemem Keeper.appを好きな場所に置いて(「ホーム/ライブラリ/Scripts」推奨)、 ダブルクリックで起動する。 すると次に下のような画面が現れるので、空きメモリの下限値を設定する。

空きメモリ下限値設定画面
1MBでも10000000MBでも対応可能だが、0やマイナスの数値を入力された時のことを考えていないのはヒミツだ対応しました。 キャンセルを押してもちゃんと終了できるようにしました(←してなかったの?)。

あとは放っておけば勝手に1分毎に一度空きメモリをチェックし、 設定値以下になっていたら下の画面を表示し、OKを押すとメモリ解放スクリプトが走る。

Release Memory起動の表示
紳士的に動作を予告する機能付き。拒否権は与えられない。

ちなみにGrowlだとこんな。
Growl版起動表示
こちらも拒否権は与えられない。

メモリ解放の努力が終了すると、下の画面が表示され、作業の完了を告げる。

Release Memory動作終了の表示
紳士的に作業の完了を告げる機能付き。拒否権は与えられない。

Growl版
Growlだとこんな。

以上がこのスクリプトの全貌だ。
隠し機能とかは特にないので探さない方が吉。

ということで、今回からは「Freemem Keeper」でメモリ解放の役割も果たすため、 手動でメモリ解放をさせたい人はこちらを使って下さいということで。

<追記>
基本的に動作させっぱなしでよいのだが、終了させておいた方がいいケースが存在するようだ。 以下、mutaさんの紹介記事からの引用。

プロセスが全て自動化されているので、ユーザは起動させたらあとは放ったらかしでいい。 注意点はCDなどの焼き焼き中やディスクのバックアップを取っている時にはこれを終了させることを忘れないことだ。 そういう作業中にこれが作動されると、CDはお釈迦、バックアップも最初からやり直しになる。

またSafariなどドックにしまった状態で、これが作動するとそれ以降Safariが操作不能になる不具合が起きる。 これはこのスクリプトのせいというよりは、Safari3とシステムの相性の問題だと思われる。 Freemem Keeperとは関係無しに、「隠す」動作の後ウインドウそのものが操作不能になる不具合が頻発するからだ。

ということなので、必要に応じて終了させてやって欲しい。 (ちなみにわたしはバックアップにDeja Vuを使っているが、 バックアップ中に発動しても特に問題なかった。) 他にも不具合が起きるケースはあると予想されるので、 見つけた方はコメント等で連絡いただけるとありがたい。

対応策としては、mutaさんも書かれているようにFreemem Monitorを使えば勝手に発動はしない。 使い分けて欲しい。
</追記>

以下、ソースを書く。興味がある人はどうぞ。




set temp_delim to AppleScript's text item delimiters

--set the minimum limit number of Free memory(MB)
--propertyでなくても、ハンドラ内でglobal宣言すればOK

repeat

set errorFlag to false

try
set alarm_size to text returned of (display dialog "Input the limit memory size(MB)." default answer "200")
on error
set cancelFlag to true
exit repeat
end try


--in case the number is less of than or equal to 0
try
if alarm_size is less than or equal to 0 then error
on error
set errorFlag to true
set alarm_size to 0
end try

if not errorFlag then exit repeat

end repeat


--error処理

try
if cancelFlag then
display dialog ("キャンセルされました") buttons {"終了"}
set cancelFlag to ""
quit
end if
on error

end try


--リミット値をページ単位に換算 (1024^2)/4096=256

try
set alarm_pages to alarm_size * 256
on error
display dialog ("can not set alarm_pages")
end try


--監視間隔(秒)の設定
property waiting_interval : "60"

tell application "GrowlHelperApp"
-- Make a list of all the notification types
-- that this script will ever send:
set the allNotificationsList to ?
{"Start Running", "Finish Running"}

-- Make a list of the notifications
-- that will be enabled by default.
-- Those not enabled by default can be enabled later
-- in the 'Applications' tab of the growl prefpane.
set the enabledNotificationsList to ?
{"Start Running", "Finish Running"}

-- Register our script with growl.
-- You can optionally (as here) set a default icon
-- for this script's notifications.
register as application ?
"Freemem Keeper" all notifications allNotificationsList ?
default notifications enabledNotificationsList ?
icon of application "Script Editor"
end tell


on idle

--Mach Virtual Memory Statistics(vm_stat)から空きメモリページ数を取得
global alarm_pages, alarm_size, temp_delim

set AppleScript's text item delimiters to return
set vm_stats to do shell script "vm_stat | grep Page"
set free_mem to text item 1 of vm_stats

set AppleScript's text item delimiters to " "
set free_size to (last text item of free_mem) as number


-- Main part of the script.
-- When Free memory is less than set number,
-- run Release Memory script to prevent memory shortage.
if free_size is less than alarm_pages then

-- Run Release Memory
--display dialog "Release Memory 起動!" buttons {"OK"}

tell application "GrowlHelperApp"
-- Send a Notification...
notify with name ?
"Start Running" title ?
"Start Running" description ?
"Release Memory started." application name "Freemem Keeper"

end tell

-- Restart Finder
tell application "Finder"
quit
delay 1

try
tell application "Finder" to activate
on error
delay 1
tell application "Finder" to activate
end try


if exists Finder window 1 then
activate
set windowBounds to (bounds of Finder window 1)
set theFolder to target of Finder window 1
close Finder window 1
open theFolder
set bounds of Finder window 1 to windowBounds
end if

end tell

--on activateFinder()
-- try
-- tell application "Finder" to activate
-- on error
-- activateFinder() of me
-- end try
-- end of activateFinder()

-- end of restart Finder


-- restart Dock
do shell script "killall Dock"


--delete Dashboard cache
do shell script "rm -rf ~/Library/Caches/DashboardClient/*"


-- Run Repair Permissions via an AppleScript - macosxhints.com
-- http://www.macosxhints.com/article.php?story=20030120061404240
-- MXanadu62さんの指摘により管理者権限省略
do shell script "diskutil repairPermissions /"

--End of Release Memory
--display dialog "Release Memory 完了!" buttons {"OK"}

tell application "GrowlHelperApp"
notify with name ?
"Finish Running" title ?
"Finish Running" description ?
"Release Memory finished." application name "Freemem Keeper"

end tell

end if

set AppleScript's text item delimiters to temp_delim

return waiting_interval

end idle



まとめ

  • 空きメモリを監視し、設定値以下になったらメモリ解放を試みるAppleScript「Freemem Keeper」を作成
  • これ一つ走らせておけば、残りメモリに目を光らせていなくてよくなるので結構便利
  • といっても特定のアプリのメモリが肥大化してしまうと、あまりメモリを解放できなくなるので、そういうときはそのアプリを一度終了する

まだ完成していない部分もあると思うので、フィードバックをお願いしたい。 あと、やっていることはシステムメンテなので特に害はないと思うが、 まぁご利用は自己責任ということで・・・

ということで皆さまご機嫌よう。

追記)
各所で紹介して頂いた。ありがとうございます。m(_*_)m
自分では補足しきれていないところもあるので、参考にされたい。

web拍手とは

トラックバック

このエントリーのトラックバックURL:
http://soap.s216.xrea.com/umu/mt/mt-trackback-script.cgi/1227

コメント (12)

じゅん:

つまり、起動しっぱなしということでよいのでしょうか。

はい。何もしていないときは、CPU占有率0%であることを確認しています。

ざんしゅ:

終了時にDashboardを一瞬だけ起動するようにするにはどうすれば良いのでしょうか?

ざんしゅさん

Dashboardのcacheを削除するため、次の起動に時間がかかることを回避したいというリクエストと理解しました。
とすると、解決法は以下の2つです。お好きな方をどうぞ。
どちらも、Freemem Keeperを「アプリケーション>AppleScript>スクリプトエディタ」で開いて編集して下さい。


1.cacheの削除をしないようにする
do shell script "rm -rf ~/Library/Caches/DashboardClient/*"

という行の先頭に、下のように「--」を追加してコメントアウトする。

--do shell script "rm -rf ~/Library/Caches/DashboardClient/*"

2.メモリ解放プロセスの最後にDashboardの起動を入れる

--End of Release Memory の行の上に、
以下のコードをコピペして下さい。

tell application "System Events"
key code 111
end tell

delay 2

tell application "System Events"
key code 111
end tell


delayの数字が待ち時間なので、適当に変更して下さい。

MXanadu62:

ハルさま。ご無沙汰です。

Leopardが走るんですね。うらやましい…。f(^^;

Freemem Keeperについて細かいことですが、ちょっと気になったことを…。

1.起動後に終了させるのは強制終了させるのでしょうか?
もしその場合はon idleハンドラ内に「set AppleScript's text item delimiters to temp_delim」を持ってきた方が、作法としては正しいように思います。
強制終了してもスクリプトエディタで調べると、デリミタが初期値である「{""}」から変わったままにはならないようですが…。
ちなみにFreemem Keeper内で表示させるとデリミタは変更されています。on idleハンドラ内に以下を埋め込むと確認できます。
display dialog ascii number of (AppleScript's text item delimiters as text)

2.起動時に初期画面を表示させているのは意図があってのことですか?(余計なお世話!)
これは保存時にチェックボックスを外せば出ないようになりますが…。

MXanadu62さん
ご指摘どうもです。とりあえず反映させてみました。

現状もっぱらの関心は、Leopardで効き目がないことです。LeopardではSwapfileが6個できてても、あまり動作が遅くならないんですよね。
その辺なにか改良されたんでしょうかね。

MXanadu62:

> 現状もっぱらの関心は、Leopardで効き目がないことです。

Loepardのアクセス権修復にはバグがあるようですね。
日本のディスカッションルームは嫌い(笑)なので見てませんが、本家のディスカッションルームに以下のスレッドが立っています。
http://discussions.apple.com/thread.jspa?messageID=5662841

いろいろごちゃごちゃ書いてありますが、以下のMacFixItの記事に代表されるようです。
http://www.macfixit.com/article.php?story=20071031102625632

コマンドラインでもディスクユーティリティでもアクセス権を修復できないようですね。
本来の働きができないから、メモリ解放もできないのではないでしょうか?

> LeopardではSwapfileが6個できてても、あまり動作が遅くならないんですよね。
> その辺なにか改良されたんでしょうかね。

Leopardが走るMacでないので分かりません。(笑)
でも、基本的にUnixから引き継いだ仕組みだから、大変更がされているとは考えにくいと思うんですが…。

MXanadu62さん

情報ありがとうございます。
細かいエラーメッセージはさておき、私が感じていることは他でも確認されているとわかりました。とりあえずupdate待ちですかね。

>でも、基本的にUnixから引き継いだ仕組みだから、大変更がされているとは考えにくいと思うんですが…。

とりあえずswapfileが4つ以上作られたときの虹色カーソルぐるぐる状態は大分良くなっている印象です。OS内部の細かい仕組みが変わっているものと思います。


adocha:

10.5にいれてみました〜〜 勝手にスリープとか再起動しますか?などのダイアログがでるみたいです〜〜〜

haru:

adochaさん、どうもです。

人柱ありがとうございますm(_*_)m

私も今Leopard上で起動し、様子を見ているのですが、特にそういったメッセージは出てこないみたいです。

何かのアプリケーションと相性が悪いのかもしれませんね。

もし何かわかりましたら、教えていただけると助かりますです。

ゆすけsun:

ひっそりと、お世話になっておりますw
あまり詳しくないので、とんちんかんな質問かもしれませんが…、

freemem monitor使わせていただいているのですが、作動する際、毎回ログインパスワードをきかれるんですが、これを回避して自動実行させてくれる方法はないでしょうか?
OSは、10.5.6使ってます。

haru:

ゆすけsunさん、どうもです。

パスワードの入力ですが、回避する方法はあります。が、AppleScriptに平分でパスワードを書く方法しかわからず、セキュリティ的に微妙なので書いてません。

わかった上でやられるのであれば問題ないので、手順を以下に書きます。

1.Freemem Monitorをスクリプトエディターで開く

2.以下の行を探す

--4.Update locate database
do shell script "/usr/libexec/locate.updatedb" with administrator privileges

3.以下のように書き換える

--4.Update locate database
do shell script "/usr/libexec/locate.updatedb" password "パスワードを記入" with administrator privileges


4.保存して(必要であれば名前を変えて)終了

「パスワードを記入」の部分をパスワードに書き換えてください(""は残します)。
これでパスワードは聞かれなくなるはずです。お試しください。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

最近のトラックバック

アーカイブ

別館(annex)との統合フィードを取得
[フィードとは]
Add to Google
はてなRSSへ追加
My Yahooへ追加
Livedoorへ追加
gooへ追加
購読する Bloglines


Powered by FeedBurner

メールで購読
メールアドレスを入力してください:

配信: FeedBurner


このブログ単独のフィードを取得

クリエイティブ・コモンズ

Creative Commons License
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.
Powered by
Movable Type