バックグラウンドになったアプリを一時停止して劇的に軽くするAppleScript

元ネタは以下のページ。(素晴らしい発想に感激!)

全くそのとおりで、自分の場合もSafariで常時50以上のタブと複数のウィンドウを開いて作業しているのだ。ブックマークするほどでもないけど、後で試してみたいこととか、この日記を書いている間は頻繁に参照しそうだから開いておこうとか、諸々の理由でついついタブを開き過ぎる傾向にある。その結果、アイドル時のCPU利用率の増加、メモリの空き容量残りわずか、swap頻発。そして、重〜いMacBookにイラつく結果となるのだ。

この状況を打破すべく考案されたのが、プロセスにSIGSTOPシグナルを送信して、バックグラウンドで利用していないアプリを完全に停止状態にしてしまう方法。SIGSTOP中のプロセスのCPU利用率は0になるのだ。
面白そう!こうゆうのを見ると、絶対に試したくなる。さっそく試してみると、Safariは見事、バックグラウンドでは完全に停止し、フォアグラウンド(アクティブな状態)になると再び再開された。CPU利用率もSafariの利用率分、激減したのだ。

日曜研究室さんは、Pythonからappscript経由でSIGSTOP・SIGCONTの自動送信を実現している。appscriptは、AppleEventを扱うらしい。つまり、AppleScriptでも同じことが実現できるということだ。ならば自分は、AppleScriptでやってみようと思っていた。そのうちやってみようと思っていらた、既にAppleScript版が発表されていた!

なるほど。choose from list を使うことで、よりGUIアプリっぽく実装することができるのか...。開拓者お二方のコードを参考にしつつ、自分でもやってみた。

スクリプト


property STOP_app_names : {}
on run --起動時に実行
if STOP_app_names = {} then
my select_app() end if
end run

on reopen --Dockのアイコンをクリック時に実行
my select_app() end reopen

on idle --繰り返し実行
my sigstop_or_sigcont_all() return 1
end idle

on quit --終了時に実行
my sigcont_all() continue quit
end quit



on select_app() activate
"バックグラウンドで一時停止するプロセスを選択してください。
(commandキーで複数選択 可)"
set select_app_names to ¬ choose from list my process_names() with prompt result ¬ default items STOP_app_names ¬ with multiple selections allowed and empty selection allowed
if select_app_names is not false then
my sigcont_all() set STOP_app_names to select_app_names
end if
end select_app

on process_names() tell application "System Events"
set process_list to processes's name whose visible is true
end tell
end process_names

on frontmost_bool(app_name) tell application "System Events"
processes's frontmost whose name is app_name
end tell
end frontmost_bool

on sigstop_or_sigcont_all() repeat with app_name in STOP_app_names
try
if my frontmost_bool(app_name) then
do shell script "killall -SIGCONT " & app_name's quoted form
else
do shell script "killall -SIGSTOP " & app_name's quoted form
end if
end try
end repeat
end sigstop_or_sigcont_all

on sigcont_all() repeat with app_name in STOP_app_names
try
do shell script "killall -SIGCONT " & app_name's quoted form
end try
end repeat
end sigcont_all

  • 上記スクリプトを「SIGSTOP.app」として保存した。
    • フォーマット:アプリケーション
    • オプション :「実行後、自動的に終了しない」をチェック入


仕様

  • 初回起動時、バックグラウンドで一時停止したいプロセスを選択する。
  • プロセスリストから複数選択可能。(commandキーを押しながら選択する)

  • 次回以降はプロセスの監視が即始まる。(前回選択した一時停止したいプロセスを記憶している)
  • SIGSTOP.appを終了すれば、一時停止したいプロセスは解除され、常時稼働状態になる。
  • 一時停止したいプロセスを再度選択したい時は、DockのSIGSTOP.appアイコンをクリックする。

所感

まだそれほど使い込んでいないが...

  • AppleScript版SIGSTOP.appのCPU利用率は、1.5〜2.0ぐらい。(1秒間隔で監視)
  • 一方、Python版appsl.pyのCPU利用率は、0.3〜0.4くらい。(0.5秒間隔で監視)
  • Python版の方が効率がいい。
  • 確かにアイドル時のCPU利用率は激減した。
  • しかし、メモリ使用量はそのまま。よって、swapは今まで通り発生することになる。
  • CPU利用率が高くても操作感が軽い状況もある。
  • ブラウザの場合、CPU利用率が多少高くても、それほど操作感は重くならない。
  • ブラウザのCPU利用率よりは、ブラウザが大量に確保するメモリによってswapが発生し、
  • swapのCPU利用率によって、どうしようもなく重い操作感になることが多いようだ。

しばらく使ってみることにする。