Ich mag laute Hardware nicht. Und ich fand es gut, dass mein iBook mit 600MHz PowerPC G3 Prozessor aus dem Jahr 2001 nur im absoluten Notfall den Lüfter eingeschaltet hat. Auch mein MacBook Pro mit 2,4GHz Intel Core 2 Duo Prozessor war im Normalfall nicht zu hören.
Aber mein neues MacBook Pro mit 2,2GHz Intel Core i7 erdreistet sich, bei verschiedenen Gelegenheiten, in den „Jet-mode“ zu gehen. Die Ursache ist dann gern mal der Indexer für Spotlight (metadata server – mds) oder ein Video Player (video lan client – vlc). Beide brauchen eigentlich nicht mit voller Power zu laufen um meinen Ansprüchen gerecht zu werden. Ausserdem braucht man meist auch die dedizierte Grafikkarte nicht. Die kann man aber Dank gfxCardStatus einfach abschalten. Achtung, nicht vergessen wieder anzuschalten, wenn man den Beamer dranhängt!
Apple hat leider keine Möglichkeit vorgesehen die CPU zu drosseln um weniger Strom zu verbrauchen und somit den Akku und das Gehör zu schonen. Todtraurig!
Nice ist auch keine Lösung, weil ja dennoch die Power genutzt wird die zur Verfügung steht.
Aber ich habe etwas gefunden was an dieser Stelle weiterhelfen kann: cpulimit. Das ließ sich aber unter Lion nicht compilieren. Es gibt da aber noch diese Variation davon.
An der Shell Variante habe ich ein wenig gefeilt. Nun bekommt man eine Liste der CPU hungrigen Prozesse zur Auswahl und den Erstplatzierten als Vorauswahl.
Das Ergebnis sieht dann so aus:
$ sudo ~/bin/cpulimit.sh
Password:
This script will throttle a chosen process as you like it.
Therefore your cpu runs cooler - hopefully.
Chose which process to throttle:
PPID PID USER %CPU %MEM STARTED TIME STIME COMMAND
1 66 root 25,5 5,1 Do08am 73:25.42 32:24.31 mds
273 436 bschmidt 23,1 0,1 Do08am 1:20.18 0:13.72 Folder Actions Dispatcher
1 19304 root 15,3 0,1 Sa03pm 62:40.11 51:14.03 activitymonitord
273 91519 bschmidt 14,6 0,3 7:57pm 0:06.47 0:02.17 mdworker
1 12 _mdnsresponder 12,6 0,0 Do08am 26:20.00 19:02.96 mDNSResponder
273 91189 bschmidt 11,6 0,4 7:55pm 0:06.54 0:02.21 mdworker
273 91520 bschmidt 11,3 0,3 7:57pm 0:06.48 0:02.17 mdworker
273 91518 bschmidt 9,2 0,3 7:57pm 0:06.36 0:02.14 mdworker
273 13471 bschmidt 8,7 3,6 Fr02pm 101:01.25 22:25.71 Google Chrome
Which process ID (PID) [guess: 66]?
Chosen:
PID USER %CPU %MEM STARTED TIME COMMAND
66 root 21,9 5,1 Do08am 73:26.43 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds
Sleep time in seconds (e.g 0.5 or 1 …) [default: 0.5]?
Run time in seconds (e.g 0.5 or 1 …) or percent [default: .5000 = 50%]?
OK. I will throttle PID 66 now and dislay processinfo every 20 seconds …
PID USER %CPU %MEM STARTED TIME COMMAND
66 root 40,5 4,7 Do08am 73:34.02 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds
PID USER %CPU %MEM STARTED TIME COMMAND
66 root 32,7 4,8 Do08am 73:34.91 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds
PID USER %CPU %MEM STARTED TIME COMMAND
66 root 0,0 4,8 Do08am 73:35.15 /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds
^C
*** Ouch! Stop throtteling of PID 66. Exiting ***
Mit diesem Script ist es ein Leichtes, Prozesse ausser Rand und Band wieder einzufangen. Erstaunlicher Weise sogar den Video Player, wenn man nur die sleep time kurz genug wählt.
Da das Script nicht lang ist, stell ich es hier einfach mal rein:
#! /bin/bash
# Description:
#
# If you want to decrease the CPU demands for an application
# you can use this very simple and ugly "hack".
# I use it when I convert videos on my MacBook Pro
# to prevent it from getting to warm. Even if the CPU is IDLE this hack
# will prevent the application to use the CPU during Sleep Time
# (in contrast to renice/nice commands which will take all IDLE time).
# This means the conversions will take longer time, but I
# don't care because I run it at night.
#
# There is similar c program for Linux called cpulimit, but it wont
# compile on my Mac.
#
# Usage: sudo ./cpulimit.sh
#
#################################
# config
sleeptime_default=0.5 # in seconds
runtimep_default=50 # in percent (50 = same as sleeptime)
reporttime=30 # report every x seconds while running
# PROCESSLISTformat: pid has to be on the second position
PROCESSLISTformat="ppid,pid,user,%cpu,%mem,start,cputime,stime,command"
#PROCESSLISTformat="ppid,pid,user,%cpu,%mem,start,cputime,stime,rss,vsz,cpu,re,wq,wqr,stat,nsigs,command"
#################################
# dont change anything below here
pid=""
scriptuser=$(id -u)
# run if user hits control-c
control_c()
{
echo ""
if [ "$pid" != "" ]; then
echo -en "\n*** Ouch! Stop throtteling of PID $pid. Exiting ***\n"
kill -SIGCONT $pid
fi
echo ""
exit $?
}
# trap keyboard interrupt (control-c)
trap control_c SIGINT
pidstring()
{
# takes pid as argument
ps -p $1 -w -o pid,user,%cpu,%mem,start,cputime,command 2>/dev/null
}
isnumber()
{
if [[ "$1" =~ ^[0-9]*([.][0-9]+)?$ ]] ; then
return 0
else
return 1
fi
}
#################################
# main
cat << EOF
This script will throttle a chosen process as you like it.
Therefore your cpu runs cooler - hopefully.
EOF
if [ "$scriptuser" != "0" ]; then
cat << EOF
You're not root!
If you want to controll processes that you dont own,
please run via sudo.
EOF
fi
PIDSTRING=""
until [ "$PIDSTRING" != "" ]; do
#PROCESSLIST=$(ps -r -A -f -S | head)
if [ "$scriptuser" != "0" ]; then
PROCESSLIST=$(ps -r -u $scriptuser -S -c -o $PROCESSLISTformat 2>/dev/null)
else
PROCESSLIST=$(ps -r -A -S -c -o $PROCESSLISTformat 2>/dev/null)
fi
if [ "$PROCESSLIST" = "" ]; then
echo -en "\n*** Sorry, ps dont work as expected on $(uname). Exiting ***\n\n"
exit 1
else
PROCESSLIST=$(echo "$PROCESSLIST" | head)
fi
echo -en "\nChose which process to throttle:\n$PROCESSLIST\n"
PID_GUESS=$(echo "$PROCESSLIST" | head -2 | tail -1 | awk '{print $2}')
echo -n "Which process ID (PID) [guess: $PID_GUESS]? "
read pid
if [ "$pid" = "" ]; then
pid=$PID_GUESS
fi
# test if $pid is valid
PIDSTRING=$(pidstring $pid)
if [ "$?" -eq "0" ]; then
echo -en "\nChosen:\n$PIDSTRING\n"
else
echo -en "\n$pid is not a valid PID for a running process.\n"
pid=""
fi
echo -en "\n"
done
sleeptime=""
until [ "$sleeptime" != "" ]; do
echo -n "Sleep time in seconds (e.g 0.5 or 1 …) [default: $sleeptime_default]? "
read sleeptime
if [ "$sleeptime" = "" ]; then
sleeptime=$sleeptime_default
fi
isnumber $sleeptime || sleeptime=""
done
#echo "sleeptime $sleeptime"
runtime=""
until [ "$runtime" != "" ]; do
runtime_default=$(echo "scale=4;$sleeptime*$runtimep_default/(100-$runtimep_default)"|bc)
echo -n "Run time in seconds (e.g 0.5 or 1 …) or percent [default: $runtime_default = $runtimep_default%]? "
read runtime
if [[ "$runtime" =~ ^([0-9]*([.][0-9]+)?)%$ ]] ; then
runtimep_default=${BASH_REMATCH[1]}
fi
if [ "$runtime" = "" ]; then
runtime=$runtime_default
fi
isnumber $runtime || runtime=""
done
#echo "runtime $runtime"
# now begin throttle
throttletime=1000000
looptime=$(awk "BEGIN { printf \"%.0f\\n\", ($sleeptime+$runtime)*100 }")
echo "OK. I will throttle PID $pid now and dislay processinfo every $reporttime seconds … "
((reporttime=$reporttime*100))
while true
do
if [ $throttletime -ge 500 ]; then
throttletime=0
PIDSTRING=$(pidstring $pid)
echo "$PIDSTRING"
fi
kill -SIGSTOP $pid || control_c
sleep $sleeptime
kill -SIGCONT $pid || control_c
sleep $runtime
throttletime=$(($looptime+$throttletime))
done
This is a very handy script, works perfect for me. Thanx a million.
Hallo,
ich habe es tatsächlich geschafft, das Script auszuführen. Ich habe dabei aber eine Frage. Dort wird nach der Sleeptime gefragt. Ich möchte Handbrake ein bisschen drosseln und es eigentlich nicht schlafenlegen. Ist das dennoch richtig so?
Viele Grüße