Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 327 lines (293 sloc) 14.6 KB
#!/bin/bash
# throttle - user discrection power management utility
while (( "$#" )); do
#Find the number of physical cores (for hyperthreading control)
CORES="$(grep "^core id" /proc/cpuinfo | sort -u | wc -l)"
case "$1" in
full|performance|true|1|cut|powersave|false|0)
case "${1}" in
full|performance|false|0)
HYPERTHREADS="1"
GOVERNOR="performance"
XPSTURBO="0"
ENERGYPERF="0"
BACKLIGHT="2" # Higher?
LAPTOP="0"
DIRTYWBC="500"
NMIDOG="0" # Always off
POLICY="max_performance"
APM="255"
AAM="254"
CONTROL="on"
AUTOSUSPEND="-1"
DISKAUTOSUSPEND="-1"
POWERSAVE="0"
CONTROLLER="N"
WLPOWERSAVE="off"
WOLA="g"
WOLB="enabled"
LEDBRIGHT="255"
NVPM="1"
;;
cut|powersave|true|1)
HYPERTHREADS="0"
GOVERNOR="powersave"
XPSTURBO="1"
ENERGYPERF="15"
BACKLIGHT="0"
LAPTOP="5"
DIRTYWBC="1500"
NMIDOG="0"
POLICY="min_power"
APM="1"
AAM="128"
CONTROL="auto"
AUTOSUSPEND="1"
DISKAUTOSUSPEND="60000"
POWERSAVE="1"
CONTROLLER="Y"
WLPOWERSAVE="on"
WOLA="d"
WOLB="disabled"
LEDBRIGHT="0"
NVPM="0"
;;
esac
# Hyperthreads
for i in /sys/devices/system/cpu/cpu*/online; do \
[[ "$(printf "${i}" | tr -cd [:digit:])" -ge "${CORES}" ]] && \
printf "${HYPERTHREADS}" > "${i}" ; done &
[[ "${HYPERTHREADS}" == "1" ]] && wait
# CPU Governor
for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \
[[ "${HYPERTHREADS}" == "0" && "$(printf ${i} | tr -cd [:digit:])" -ge "${CORES}" ]] && \
continue ; printf "${GOVERNOR}" > "${i}" & done &
# Disable Intel P-State Turbo
[[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \
printf "${XPSTURBO}" > /sys/devices/system/cpu/intel_pstate/no_turbo &
# ENERGY_PERF_BIAS
[[ -n "$(command -v x86_energy_perf_policy)" ]] && \
x86_energy_perf_policy "${ENERGYPERF}" &
# Backlight
[[ -f /sys/class/backlight/acpi_video0 ]] && \
for i in /sys/class/backlight/acpi_video*/brightness; do \
printf "${BACKLIGHT}" > "${i}" & done &
# Virtual Memory (Swap)
[[ "$(sysctl -n vm.laptop_mode)" == "${LAPTOP}" ]] || \
printf "${LAPTOP}" > /proc/sys/vm/laptop_mode &
[[ "$(sysctl -n vm.dirty_writeback_centisecs)" == "${DIRTYWBC}" ]] || \
printf "${DIRTYWBC}" > /proc/sys/vm/dirty_writeback_centisecs &
[[ "$(sysctl -n vm.dirty_expire_centisecs)" == "${DIRTYWBC}" ]] || \
printf "${DIRTYWBC}" > /proc/sys/vm/dirty_expire_centisecs &
# NMI watchdog
[[ -f /proc/sys/kernel/watchdog ]] && \
printf "${NMIDOG}" > /proc/sys/kernel/watchdog &
# SATA link power management
for i in /sys/class/scsi_host/host*/link_power_management_policy; do [[ -f "${i}" ]] && \
printf "${POLICY}" > "${i}" & done &
# Hard drives
[[ -n "$(command -v hdparm)" ]] && \
hdparm -qB "${APM}" -qM "${AAM}" /dev/[hs]d[a-z] 2> /dev/null &
# Block device autosuspend
for i in /sys/block/*/device/power/autosuspend_delay_ms; do \
printf -- "${DISKAUTOSUSPEND}" > "${i}" & done &
# Runtime power management for devices (with exceptions for devices by VID:PID)
for i in /sys/{class/*,bus/*/devices}/*/power/control; do \
[[ "${CONTROL}" == "auto" ]] && \
[[ -n "$(printf ${i} | grep msr[${CORES}-$((${CORES} * 2 - 1))])" || \
-n "$(printf ${i} | grep machinecheck[${CORES}-$((${CORES} * 2 - 1))])" || \
-n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 046D\:C52B)" || \
-n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 054C\:0268)" || \
-f "$(printf ${i} | sed 's|/power.*|/idVendor|g')" && \
"$(cat $(printf ${i} | sed 's|/power.*|/idVendor|g'))" == "0424" && \
"$(cat $(printf ${i} | sed 's|/power.*|/idProduct|g'))" == "a700" ]] && \
continue ; printf "${CONTROL}" > "${i}" & done &
# USB Autosuspend (with exceptions for devices by VID:PID)
for i in /sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}; do \
[[ "${AUTOSUSPEND}" == "1" ]] && \
[[ -n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 046D\:C52B)" || \
-n "$(ls $(printf ${i} | sed 's|power.*||g')/*/ | grep 054C\:0268)" || \
-f "$(printf ${i} | sed 's|/power.*|/idVendor|g')" && \
"$(cat $(printf ${i} | sed 's|/power.*|/idVendor|g'))" == "0424" && \
"$(cat $(printf ${i} | sed 's|/power.*|/idProduct|g'))" == "a700" ]] && \
continue ; printf -- "${AUTOSUSPEND}" > "${i}" & done &
# Powersaving for modules
for i in /sys/module/*/parameters/power_save; do \
printf "${POWERSAVE}" > "${i}" & done &
for i in /sys/module/*/parameters/power_save_controller; do \
printf "${CONTROLLER}" > "${i}" & done &
# Network powersaving
for i in /sys/class/net/wl*; do \
[[ -n "$(command -v iw)" ]] && \
iw dev "$(printf ${i} | sed 's/^.*wl/wl/')" set power_save "${WLPOWERSAVE}" 2> /dev/null & done &
for i in /sys/class/net/e*; do \
[[ -n "$(command -v ethtool)" ]] && \
ethtool -s "$(printf ${i} | sed 's/^.*e/e/')" wol "${WOLA}" 2> /dev/null & done &
for i in /sys/class/net/*/device/power/wakeup; do \
printf "${WOLB}" > "${i}" & done &
# LEDs
for i in /sys/class/leds/*/brightness; do \
printf "${LEDBRIGHT}" > "${i}" & done &
# Nvidia PowerMizer
[[ -n "$(command -v nvidia-settings)" ]] && \
DISPLAY=":0.0" nvidia-settings -a [gpu:0]/GPUPowerMizerMode="${NVPM}" > /dev/null &
shift
unset GOVERNOR XPSTURBO HYPERTHREADS ENERGYPERF BACKLIGHT LAPTOP DIRTYWBC NMIDOG \
POLICY APM AAM CONTROL AUTOSUSPEND POWERSAVE CONTROLLER \
WLPOWERSAVE WOLA WOLB LEDBRIGHT NVPM
;;
ht*)
case "${1}" in \
ht-on) HYPERTHREADS="1" ;; \
ht-off) HYPERTHREADS="0" ;; esac
[[ -z "${HYPERTHREADS}" ]] && \
case "${2}" in \
on|performance) HYPERTHREADS="1"; SHIFT="2" ;; \
off|powersave) HYPERTHREADS="0"; SHIFT="2" ;; esac
[[ -z "${HYPERTHREADS}" ]] && \
printf "${0} ht {on,off} - Hyperthreads\n" || \
for i in /sys/devices/system/cpu/cpu*/online; do [[ "$(printf "${i}" | tr -cd [:digit:])" -ge "${CORES}" ]] && \
printf "${HYPERTHREADS}" > "${i}" ; done &
[[ "${HYPERTHREADS}" == "1" ]] && wait
[[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift
unset HYPERTHREADS SHIFT
;;
gov*)
case "${1}" in \
gov-full) GOVERNOR="performance" ;; \
gov-cut) GOVERNOR="powersave" ;; esac
[[ -z "${GOVERNOR}" ]] && \
case "${2}" in \
full|performance) GOVERNOR="performance"; SHIFT="2" ;; \
cut|powersave) GOVERNOR="powersave"; SHIFT="2" ;; esac
[[ -z "${GOVERNOR}" ]] && \
printf "${0} gov {cut,full} - CPU Governor\n" || \
for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \
[[ "$(printf ${i} | tr -cd [:digit:])" -ge "${CORES}" && \
"$(cat /sys/devices/system/cpu/cpu$(printf ${i} | tr -cd [:digit:])/online)" == 0 ]] && \
continue ; printf "${GOVERNOR}" > "${i}" & done &
[[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift
unset GOVERNOR SHIFT
;;
turbo*)
case "${1}" in \
turbo-on) XPSTURBO="0" ;; \
turbo-off) XPSTURBO="1" ;; esac
[[ -z "${XPSTURBO}" ]] && \
case "${2}" in \
on|performance) XPSTURBO="0"; SHIFT="2" ;; \
off|powersave) XPSTURBO="1"; SHIFT="2" ;; esac
[[ -z "${XPSTURBO}" ]] && \
printf "${0} turbo {on,off} - Intel P-State Turbo\n" || \
[[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \
printf "${XPSTURBO}" > /sys/devices/system/cpu/intel_pstate/no_turbo &
[[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift
unset XPSTURBO SHIFT
;;
backlight)
case "${2}" in \
0|powersave) BACKLIGHT="0"; SHIFT="2" ;; \
1) BACKLIGHT="1"; SHIFT="2" ;; \
2|performance) BACKLIGHT="2"; SHIFT="2" ;; esac
[[ -z "${BACKLIGHT}" ]] && \
printf "${0} backlight {0,1,2} - Backlight brightness\n" || \
for i in /sys/class/backlight/acpi_video*/brightness; do \
printf "${BACKLIGHT}" > "${i}" & done &
[[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift
unset BACKLIGHT SHIFT
;;
gpu*)
case "${1}" in \
gpu-full) NVPM="1" ;; \
gpu-cut) NVPM="0" ;; esac
[[ -z "${NVPM}" ]] && \
case "${2}" in \
full|performance) NVPM="1"; SHIFT="2" ;; \
cut|powersave) NVPM="0"; SHIFT="2" ;; esac
[[ -z "${NVPM}" ]] && \
printf "${0} gpu {cut,full} - GPU runtime powersaving (only Nvidia ATM)\n" || \
[[ -z "$(command -v nvidia-settings)" ]] && \
printf "nvidia-settings not found; only nvidia currently supported" || \
DISPLAY=":0.0" nvidia-settings -a [gpu:0]/GPUPowerMizerMode="${NVPM}" > /dev/null &
[[ -n "${SHIFT}" ]] && shift "${SHIFT}" || shift
unset NVPM SHIFT
;;
check)
printf "\nHyperthreads\n/sys/devices/system/cpu/cpu*/online\n"
for i in /sys/devices/system/cpu/cpu*/online; do \
[[ $(printf "${i}" | tr -cd [:digit:]) -ge "$CORES" ]] && \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/devices/system/cpu/||g; s|/.*||g; N;s|\n|\t|'
printf "\nCPU Governor\n/sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor\n"
for i in /sys/bus/cpu/drivers/processor/cpu*/cpufreq/scaling_governor; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/bus/cpu/drivers/processor/||g; s|/.*||g; N;s|\n|\t|'
[[ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]] && \
echo -e "\nDisable Intel P-State Turbo\n/sys/devices/system/cpu/intel_pstate/\n"\
"no_turbo\t$(cat /sys/devices/system/cpu/intel_pstate/no_turbo)"
[[ -n "$(command -v x86_energy_perf_policy)" ]] && \
printf "\nEnergy Perf Bias\n" && \
x86_energy_perf_policy -r #SUID
[[ -f /sys/class/backlight/acpi_video0 ]] && \
printf "\nBacklight\n/sys/class/backlight/\n" && \
for i in /sys/class/backlight/acpi_video*/brightness; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/backlight/||g; s|/.*||g; N;s|\n|\t|'
echo -e "\nVirtual Memory (Swap)\n/proc/sys/vm/\n"\
"laptop_mode\t\t\t$(cat /proc/sys/vm/laptop_mode)\n"\
"dirty_writeback_centisecs\t$(cat /proc/sys/vm/dirty_writeback_centisecs)\n"\
"dirty_expire_centisecs\t\t$(cat /proc/sys/vm/dirty_expire_centisecs)"
[[ -f /proc/sys/kernel/watchdog ]] && \
echo -e "\nNMI watchdog\n"\
"/proc/sys/kernel/watchdog\t$(cat /proc/sys/kernel/watchdog)"
printf "\nSATA link power management\n/sys/class/scsi_host/host*/link_power_management_policy\n"
for i in /sys/class/scsi_host/host*/link_power_management_policy; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/scsi_host/||g; s|/.*||g; N;s|\n|\t|'
[[ -n "$(command -v hdparm)" ]] && \
printf "\nHard drives\n/dev/[hs]d[a-z]\n" && \
hdparm -B -M /dev/[hs]d[a-z] 2> /dev/null | sed 'N;s|\n||g; s|/dev/||g; s|\t| |g;' #SUID
printf "\nBlock device autosuspend\n/sys/block/*/device/power/autosuspend_delay_ms\n"
for i in /sys/block/*/device/power/autosuspend_delay_ms; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/block/||g; s|/device/.*||g; s|/.*||g; N;s|\n|\t|'
printf "\nRuntime power management\n/sys/{class/*,bus/*/devices}/*/power/control\n"
for i in /sys/{class/*,bus/*/devices}/*/power/control; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/||g; s|/sys/bus/||g; s|/devices||g; s|/power/control||g; N;s|\n|\t|'
printf "\nUSB Autosuspend\n/sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}\n"
for i in /sys/bus/usb/devices/*/power/autosuspend{,_delay_ms}; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/bus/usb/devices/||g; s|/.*||g; N;s|\n|\t|'
printf "\nPower saving for modules\n/sys/module/*/parameters/power_save{,_controller}\n"
for i in /sys/module/*/parameters/power_save{,_controller}; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/module/||g; s|/parameters/.*||g; s|/.*||g; N;s|\n|\t|'
printf "\nNetwork device powersaving\n/sys/class/net/{wl*,e*,*/device/power/wakeup}\n";
[[ -n "$(command -v iw)" ]] && \
for i in /sys/class/net/wl*; do \
printf " ${i}\n$(iw dev $(printf ${i} | sed 's/^.*wl/wl/') get power_save)"; done | sed 's|^\t| |g;s|/sys/class/net/||g; s|/.*||g'
[[ -n "$(command -v ethtool)" ]] && \
for i in /sys/class/net/e*; do \
printf " ${i}\n$(ethtool $(printf ${i} | sed 's/^.*e/e/') | grep Wake-on)"; done | sed 's|^\t| |g;s|/sys/class/net/||g; s|/.*||g'
for i in /sys/class/net/*/device/power/wakeup; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/net/||g; s|/device/power/wakeup||g; s|/.*||g; N;s|\n|\t|'
printf "\nLEDs\n/sys/class/leds/*/brightness\n"
for i in /sys/class/leds/*/brightness; do \
printf " ${i}\n$(cat ${i})\n"; done | sed 's|/sys/class/leds/||g; s|/brightness||g; s|/.*||g; N;s|\n|\t|'
[[ -n "$(command -v nvidia-settings)" ]] && \
printf "\nNvidia PowerMizer\n " && \
DISPLAY=":0.0" nvidia-settings -q [gpu:0]/GPUPowerMizerMode | grep "Attribute" | sed 's|.*\[||g;s|\]):||g;s| |\t|g;s|\.$||g'
shift
;;
*|help)
[[ ! "${1}" == "help" ]] && \
printf "Invalid input: ${@}\n"
echo -e "\nRuntime power management:\n"\
"${0} {cut,full} - system-wide runtime powersaving\n"\
"${0} check - inspect runtime powersaving\n"\
"\nExtras:\n" \
"${0} gov {cut,full} - CPU Governor\n"\
"${0} turbo {on,off} - Intel P-State Turbo\n"\
"${0} ht {on,off} - Hyperthreads\n"\
"${0} backlight {0,1,2} -backlight brightness\n" \
"${0} gpu {cut,full} - GPU runtime powersaving (only Nvidia ATM)\n"\
"\nOptions can take {performace,powersave} and are stackable:\n"\
"\n${0} powersave gov full turbo on gpu full ht on check"
exit
;;
esac
[[ -z "${1}" ]] || wait # Hey, let's stop! :) *stops* ... YAY! =D
done