PR

AppNapライクにWebProcessをコントロール(cputhrottle & applescript)v2.0

AppNapもどき、結構いい感じです。
いくつか、改善しました。
AppNapライクにWebProcessをコントロール(cputhrottle & applescript)のバージョンアップ版です。

改善ポイント

  • with administrator privilegesでのパスワード確認ダイアログを表示させない
  • 終了時に起動しているcputhrottleを終了する対応
  • Firefox、Safariが起動していない場合にログがわんさか出力される不具合の対応

未解決事項

  • macがスリープ、復帰後、appnap-browser.appの配列操作に起因するエラーが発生し、appが終了する

appnap-webbrowser.app(applescript) v2.0

前提

  • cputhrottleコマンドがインストールされている。/tmp/cputhrottleに存在している
  • スクリプトを実行するユーザは管理者権限を持っている

cputhrottleは、こちら(AppNapライクにWebProcessをコントロール(cputhrottle & applescript))を参考にしてください。

ソース

以下ソースをAppleScriptエディタにコピペします。
myPasswordを自分のパスワードに書き換えてください。
ファイルフォーマット:アプリケーション、オプションとして「ハンドラの実行時に終了しない」を選んで、書き出します。
(ここではファイル名:appnap-browser.appを想定しています)

global CPU_SLOW_PERCENTAGE
global myProcessDataList
global myPassword
set myPassword to "-- 管理者パスワードに置き換えてください --"
set CPU_SLOW_PERCENTAGE to "5"
set myProcessDataList to {}

script ProcessData
	property pid : -1
	property procName : ""
	
	on new(thePid, theProcName)
		copy me to theData
		set_pid(thePid) of theData
		set_procName(theProcName) of theData
		theData
	end new
	on set_pid(value)
		set pid to value
	end set_pid
	on set_procName(value)
		set procName to value
	end set_procName
end script

on FindProcessDataList(theList, theProcName, retList)
	repeat with v in theList
		if procName of v is equal to theProcName then
			set end of retList to v
		end if
	end repeat
	return retList
end FindProcessDataList

on DeleteProcessDataList(theList, theProcName)
	set retList to {}
	repeat with v in theList
		if procName of v is not equal to theProcName then
			set end of retList to v
		end if
	end repeat
	return retList
end DeleteProcessDataList

on StartBackgroundCpuControl(theProcName, theControledList)
	tell application "System Events"
		set pList to (unix id of every process whose name contains theProcName)
		if pList is not equal to {} then
			syslog("StartBackgroundCpuControl  " & theProcName & "") of me
			repeat with unixID in pList
				syslog("cputhrottle  " & (unixID as string) & " " & CPU_SLOW_PERCENTAGE) of me
				do shell script "/tmp/cputhrottle " & (unixID as string) & " " & CPU_SLOW_PERCENTAGE & " >/dev/null 2>&1 & echo $!" password myPassword with administrator privileges
				set pid to result
				set end of theControledList to new(pid, theProcName) of ProcessData
			end repeat
		end if
	end tell
end StartBackgroundCpuControl

on StopBackgroundCpuControl(theControledList)
	syslog("StopBackgroundCpuControl  targetCount=" & (length of theControledList as string) & "") of me
	tell application "System Events"
		repeat with v in theControledList
			do shell script "kill -INT " & (pid of v as string) password myPassword with administrator privileges
		end repeat
	end tell
end StopBackgroundCpuControl



on idle
	try
		tell application "System Events"
			set activeProcs to every process whose frontmost is true
			set activeProc to item 1 of activeProcs
			tell activeProc
				set activeProcName to name
			end tell
		end tell
		if activeProcName is equal to "Safari" then
			set targetProcess to {}
			set targetProcess to FindProcessDataList(myProcessDataList, "WebProcess", targetProcess)
			if length of targetProcess is not equal to 0 then
				StopBackgroundCpuControl(targetProcess)
				set myProcessDataList to DeleteProcessDataList(myProcessDataList, "WebProcess")
			end if
		else if activeProcName is equal to "Firefox" then
			set targetProcess to {}
			set targetProcess to FindProcessDataList(myProcessDataList, "Firefox", targetProcess)
			if length of targetProcess is not equal to 0 then
				StopBackgroundCpuControl(targetProcess)
				set myProcessDataList to DeleteProcessDataList(myProcessDataList, "Firefox")
			end if
		else
			set targetProcess to {}
			set targetProcess to FindProcessDataList(myProcessDataList, "WebProcess", targetProcess)
			if length of targetProcess is equal to 0 then
				-- 制御中は、再実行しない
				StartBackgroundCpuControl("WebProcess", myProcessDataList)
			end if
			set targetProcess to {}
			set targetProcess to FindProcessDataList(myProcessDataList, "Firefox", targetProcess)
			if length of targetProcess is equal to 0 then
				-- 制御中は、再実行しない
				StartBackgroundCpuControl("Firefox", myProcessDataList)
			end if
		end if
		return 1
	on error errorMessage number errorNumber
		syslog("errorMessage: " & errorMessage & ", errorNumber: " & errorNumber)
		error
	end try
end idle

on quit
	set targetProcess to {}
	set targetProcess to FindProcessDataList(myProcessDataList, "WebProcess", targetProcess)
	set targetProcess to FindProcessDataList(myProcessDataList, "Firefox", targetProcess)
	if length of targetProcess is not equal to 0 then
		StopBackgroundCpuControl(targetProcess)
		set myProcessDataList to {}
	end if
	syslog("appnap-browser closed.")
	continue quit
end quit

on syslog(logmsg)
	do shell script "logger -t appnap-browser -i " & logmsg
end syslog

終了方法

起動すると
dockにappnap-browserアイコンが存在しています。

appnap-browserアイコンを選択後、
メニューから終了を選んでください。
(appnap-browser -> appnap-browserを終了)

新しいバージョンのスクリプトがあります。
AppNapライクにSafari,Firefoxをコントロール(cputhrottle & applescript)v3.0

タイトルとURLをコピーしました