aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Runge <dave@sleepmap.de>2018-12-05 02:11:32 +0100
committerDavid Runge <dave@sleepmap.de>2018-12-05 02:11:32 +0100
commit4a61cf893ee0c699f0f12dfa8bfe5f3fba153c17 (patch)
tree6936f46b98773beccfc52167d5a8c9e522a823ed
parent2f9dde1528974a2923cd2b8f8d8435f53bdaf435 (diff)
downloaddotfiles-4a61cf893ee0c699f0f12dfa8bfe5f3fba153c17.tar.gz
dotfiles-4a61cf893ee0c699f0f12dfa8bfe5f3fba153c17.tar.bz2
dotfiles-4a61cf893ee0c699f0f12dfa8bfe5f3fba153c17.tar.xz
dotfiles-4a61cf893ee0c699f0f12dfa8bfe5f3fba153c17.zip
bin/realtime-suggestions: Adding realtime-suggestions.
-rwxr-xr-xbin/realtime-suggestions216
1 files changed, 216 insertions, 0 deletions
diff --git a/bin/realtime-suggestions b/bin/realtime-suggestions
new file mode 100755
index 0000000..4ff8722
--- /dev/null
+++ b/bin/realtime-suggestions
@@ -0,0 +1,216 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+warning="WARNING:"
+info="INFO:"
+kernel_config="/proc/config.gz"
+sysctl_ref="(see \`man 5 sysctl.conf\`, \`man 5 sysctl.d\` or \`man 8 sysctl\` for reference)"
+
+check_root() {
+ if [ "$(id -u)" -eq 0 ]; then
+ echo "Use this script as an unprivileged user."
+ exit 1
+ fi
+}
+
+check_filesystems() {
+ local mount_points=()
+ local mount_point_data=()
+ local what=""
+ local where=""
+ local type=""
+ local options=""
+ mapfile -t mount_points < <( mount |grep -E "^/dev" )
+ for mount_point in "${mount_points[@]}"; do
+ mapfile -d " " -t mount_point_data < <( echo "${mount_point}" )
+ what="${mount_point_data[0]}"
+ where="${mount_point_data[2]}"
+ type="${mount_point_data[4]}"
+ options="${mount_point_data[5]}"
+ if [[ "$options" != *relatime* ]] && [[ "$options" != *noatime* ]]; then
+ echo "$warning $what mounted on $where (type $type) should use the relatime mount option for performance."
+ fi
+ if [[ "$type" == *fuse* ]] || [[ "$type" == *reiserfs* ]] || [[ "$type" == *vfat* ]]; then
+ echo "$info $what mounted on $where (type $type) is not a good filesystem for large files or realtime use."
+ fi
+ done
+}
+
+check_groups() {
+ local groups=""
+ groups=$(groups)
+ if [[ "$groups" != *audio* ]]; then
+ echo "$warning Add your user to the audio group. It's used for access to audio devices on most distros."
+ fi
+ if [[ "$groups" != *realtime* ]]; then
+ echo "$info Some distributions use the realtime group for elevated resource limits."
+ fi
+}
+
+check_ulimits() {
+ local limits_ref="(see \`man limits.conf\` for reference)"
+ if [[ "$(ulimit -t)" != "unlimited" ]]; then
+ echo "$warning The CPU limit for your user is not unlimited $limits_ref."
+ fi
+ if [[ "$(ulimit -l)" != "unlimited" ]]; then
+ echo "$warning The locked-in-memory limit for your user is not unlimited $limits_ref."
+ fi
+ if [ "$(ulimit -r)" -le 50 ]; then
+ echo "$warning The maximum rt priority for your user ($(ulimit -r)) is very low. Consider increasing it up to 98 $limits_ref."
+ fi
+}
+
+check_vm_swappiness() {
+ local minimum=10
+ local proc_file="/proc/sys/vm/swappiness"
+ if [ "$(cat "$proc_file")" -gt $minimum ]; then
+ echo "$warning Consider decreasing 'vm.swappiness<=$minimum' to prevent early write to swap $sysctl_ref."
+ fi
+}
+
+check_max_user_watches() {
+ local minimum=524288
+ local proc_file="/proc/sys/fs/inotify/max_user_watches"
+ if [ "$(cat "$proc_file")" -lt $minimum ]; then
+ echo "$warning Consider increasing 'fs.inotify.max_user_watches>$minimum' - the maximum amount of files inotify can watch $sysctl_ref"
+ fi
+}
+
+check_cpu_governor() {
+ local cpupower_ref="(see \`man cpupower\` for reference)"
+ local governor=""
+ local policy_no=""
+ local cpu_no=""
+ for governor_file in /sys/devices/system/cpu/cpufreq/policy*/scaling_governor; do
+ governor="$(cat "$governor_file")"
+ policy_no="$(echo "$governor_file"| cut -d'/' -f7)"
+ cpu_no="${policy_no//policy}"
+ if [[ "$governor" != "performance" ]]; then
+ echo "$warning CPU $cpu_no has governor $governor set. Set it to 'performance' $cpupower_ref."
+ fi
+ done
+}
+
+check_config_high_res_timers() {
+ local config="CONFIG_HIGH_RES_TIMERS=y"
+ local config_ref="(see \`man 7 time\` for reference)"
+ if [ -e "${kernel_config}" ]; then
+ if ! zgrep -q "$config" "$kernel_config"; then
+ echo "$warning CONFIG_HIGH_RES_TIMERS needs to be activated for your kernel $config_ref."
+ fi
+ else
+ echo "$warning $kernel_config could not be found or accessed."
+ fi
+}
+
+check_config_no_hz() {
+ local config1="CONFIG_NO_HZ_IDLE=y"
+ local config2="CONFIG_NO_HZ=y"
+ local config_ref="(see https://elinux.org/Kernel_Timer_Systems#Dynamic_ticks for reference)"
+ if [ -e "${kernel_config}" ]; then
+ if ! zgrep -q "$config1" "$kernel_config"; then
+ echo "$warning $config1 needs to be set for your kernel for 'dynamic ticks' support $config_ref."
+ fi
+ if ! zgrep -q "$config2" "$kernel_config"; then
+ echo "$warning $config2 needs to be set for your kernel for 'dynamic ticks' support $config_ref."
+ fi
+ else
+ echo "$warning $kernel_config could not be found or accessed."
+ fi
+}
+
+check_config_preempt_rt() {
+ local config1="CONFIG_PREEMPT_RT=y"
+ local config2="CONFIG_PREEMPT_RT_FULL=y"
+ local config_ref="(see https://wiki.linuxfoundation.org/realtime for reference)"
+ if [ -e "${kernel_config}" ]; then
+ if ! zgrep -q "$config1" "$kernel_config" && ! zgrep -q "$config2" "$kernel_config"; then
+ echo "$warning The PREEMPT_RT patch set is not available on your kernel $config_ref."
+ fi
+ else
+ echo "$warning $kernel_config could not be found or accessed."
+ fi
+}
+
+check_config_irq_forced_threading() {
+ local config1="CONFIG_PREEMPT=y"
+ local config2="CONFIG_IRQ_FORCED_THREADING=y"
+ local config_ref="(see https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html for reference)"
+ if [ -e "${kernel_config}" ]; then
+ if zgrep -q "$config2" "$kernel_config"; then
+ if ! zgrep -q "$config1" "$kernel_config" && ! grep -q "threadirqs" /proc/cmdline; then
+ echo "$warning Without $config1 on your kernel, you can still use the threadirqs kernel parameter $config_ref."
+ fi
+ else
+ echo "$warning Use a kernel with $config2 $config_ref."
+ fi
+ else
+ echo "$warning $kernel_config could not be found or accessed."
+ fi
+}
+
+check_legacy_timers() {
+ local hpet_file="/dev/hpet"
+ local rtc_file="/dev/rtc0"
+ local hpet_ref="(see https://wiki.linuxaudio.org/wiki/system_configuration#timers for reference)"
+ if [ ! -w "$hpet_file" ]; then
+ echo "$info $hpet_file is not writable by your user. Some legacy software requires it $hpet_ref."
+ fi
+ if [ ! -w "$rtc_file" ]; then
+ echo "$info $rtc_file is not writable by your user. Some legacy software requires it $hpet_ref."
+ fi
+}
+
+check_cpu_dma_latency() {
+ local dev_file="/dev/cpu_dma_latency"
+ if [ ! -w "$dev_file" ]; then
+ echo "$warning $dev_file needs to be writable by your user to prevent deep CPU sleep states."
+ fi
+}
+
+check_coupled_interrupts() {
+ local interrupts=()
+ local interrupt_delim=", "
+ local interrupt_number=""
+ local interrupt_ref="(see \`cat /proc/interrupts\` for more and consider using rtirq)"
+ mapfile -t interrupts < <( cat /proc/interrupts )
+ for interrupt_line in "${interrupts[@]}"; do
+ interrupt_number="$(echo "$interrupt_line"| cut -d':' -f1)"
+ if [[ "$interrupt_line" == *"$interrupt_delim"* ]]; then
+ echo "$warning IRQ$interrupt_number has coupled interrupts $interrupt_ref."
+ fi
+ done
+}
+
+check_irqbalance() {
+ if pgrep -i irqbalance >/dev/null 2>&1; then
+ echo "$warning The irqbalance service is running on your system. It might interfere, so consider disabling it."
+ fi
+}
+
+check_for_useful_tools() {
+ local tools=( cyclictest htop iostat iotop rtirq schedtool tuna )
+ for tool in "${tools[@]}";do
+ if ! command -v "$tool" >/dev/null 2>&1; then
+ echo "$info Consider installing and using $tool."
+ fi
+ done
+}
+
+check_root
+check_filesystems
+check_groups
+check_ulimits
+check_max_user_watches
+check_legacy_timers
+check_vm_swappiness
+check_cpu_governor
+check_cpu_dma_latency
+check_config_high_res_timers
+check_config_no_hz
+check_config_preempt_rt
+check_config_irq_forced_threading
+check_coupled_interrupts
+check_irqbalance
+check_for_useful_tools