From b77cfafc8cbb0f7314b28fccaa426a5c20b7ba82 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Mon, 16 May 2011 16:30:14 -0400 Subject: [PATCH] Speed improvements to several of the status programs. * cpu_freq: from: 0m4.911s, 0m0.060s, 0m0.270s to__: 0m0.147s, 0m0.130s, 0m0.010s * wifi_quality: from: 0m21.201s, 0m0.260s, 0m0.540s to__: 0m6.418s, 0m0.190s, 0m0.140s * uptime: from: 0m9.262s, 0m0.150s, 0m0.380s to__: 0m0.103s, 0m0.050s, 0m0.040s * load_avg: from: 0m4.964s, 0m0.060s, 0m0.240s to__: 0m0.083s, 0m0.040s, 0m0.040s * disk_io, network: speed improvements were harder to track to due caching. Several forks were removed in each. These are less tested though at the moment. * Add 'fpdiv' function to do floating-point-like math in shell. * Add 'rtrim' function like php 'rtrim' Time output above is ordered as 'real, user, sys' for 1000 runs on my T400 laptop, which was otherwise generally idle The 'loopit' command below is used to test speed improvements like this: time loopit 1000 . ./usr/lib/byobu/cpu_freq ## begin loopit #!/bin/sh cr() { "$@"; echo; } times=$1 shift i=0; . ./usr/lib/byobu/.shutil while [ $i -lt $times ]; do "$@" i=$(($i+1)) done ## end loopit --- usr/lib/byobu/.shutil | 29 +++++++++++++++++++++++++++++ usr/lib/byobu/cpu_freq | 4 +++- usr/lib/byobu/disk_io | 38 ++++++++++++++++++++++++++------------ usr/lib/byobu/load_average | 4 ++-- usr/lib/byobu/network | 32 +++++++++++++++++++------------- usr/lib/byobu/uptime | 12 +++++++----- usr/lib/byobu/wifi_quality | 18 +++++++++++++----- 7 files changed, 99 insertions(+), 38 deletions(-) diff --git a/usr/lib/byobu/.shutil b/usr/lib/byobu/.shutil index f02c017f..7261c983 100644 --- a/usr/lib/byobu/.shutil +++ b/usr/lib/byobu/.shutil @@ -36,3 +36,32 @@ find_script() { _RET="/dev/null" fi } + +# divide 2 integers and return a floating point number +# third argument indicates how many digits after the decimal +fpdiv() { + local a=$1 b=$2 pres=${3:-3} + local i=0 mp="10" whole="" part="" + while i=$(($i+1)) && [ $i -le $pres ]; do + mp="${mp}0" + done + whole=$(($a/$b)) + part=$((((($a%$b)*${mp})/$b))) + if [ $part -eq 0 ]; then + part=$(($mp/10)); part=${part#1}; + elif [ $((${part}%(${mp}/10))) -ge 5 ]; then + part=$(($part+5)) + fi + _RET="${whole}.${part%?}" +} + +# rtrim(string,chars) +rtrim() { + local tab=' ' cr=" +" + local cur="${1}" set="[${2:- ${tab}${cr}}]" n="" + while n=${cur%${set}} && [ "$n" != "$cur" ]; do cur=${n}; done + _RET=${cur} +} + +# vi: syntax=sh ts=4 noexpandtab diff --git a/usr/lib/byobu/cpu_freq b/usr/lib/byobu/cpu_freq index e8b3eab5..a79e003a 100755 --- a/usr/lib/byobu/cpu_freq +++ b/usr/lib/byobu/cpu_freq @@ -26,7 +26,9 @@ if [ "$1" = "--detail" ]; then fi if [ -r "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" ]; then - freq=$(awk '{ printf "%.1f", $1 / 1000000 }' /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq) + read hz < /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq + fpdiv $hz "1000000" 1 # 1Ghz + freq="$_RET" else if egrep -q -s -i -m 1 "^cpu MHz|^clock" /proc/cpuinfo; then freq=$(egrep -i -m 1 "^cpu MHz|^clock" /proc/cpuinfo | awk -F"[:.]" '{ printf "%.1f", $2 / 1000 }') diff --git a/usr/lib/byobu/disk_io b/usr/lib/byobu/disk_io index 5a042697..d4d79626 100755 --- a/usr/lib/byobu/disk_io +++ b/usr/lib/byobu/disk_io @@ -20,20 +20,26 @@ PKG="byobu" DATA="$HOME/.$PKG" color 2>/dev/null || color() { true; } +getdisk() { + local t="" + if [ -L "${1}" ]; then + command -v greadlink >/dev/null && READLINK=greadlink || READLINK=readlink + t=$($READLINK -f "$1") + else + t="$1" + fi + t="${t##*/}"; + rtrim "$t" "0-9" +} + [ "$UTF8" = "1" ] && ICON_RD="◀" || ICON_RD="<" [ "$UTF8" = "1" ] && ICON_WR="▶" || ICON_WR=">" # Default to disk providing /, but let users override with MONITORED_DISK [ -z "$MONITORED_DISK" ] && MP="/" || MP="$MONITORED_DISK" -case $MP in - /dev/*) disk="$MP" ;; - *) disk=$(grep -m 1 " $MP " /etc/mtab | sed -e "s: .*$::") ;; -esac -which greadlink 2>/dev/null && READLINK="greadlink" || READLINK="readlink" -disk=$($READLINK -f "$disk" | sed -e "s: .*$::" -e "s:^.*/::" -e "s:\([hsv]d[a-z]\)[0-9]*$:\1:") if [ "$1" = "--detail" ]; then - if which iostat >/dev/null; then + if command -v >/dev/null; then iostat -d -m -h else echo "Please install iostat if you want detailed information on your disk throughput" @@ -41,6 +47,13 @@ if [ "$1" = "--detail" ]; then exit 0 fi +case "$MP" in + /dev/*) part="${MP}";; + *) part=$(awk '$2 == mp { print $1 ; exit(0); }' "mp=$MP" /etc/mtab);; +esac +getdisk "$part" +disk=${_RET} + [ -d "/var/run/screen/S-$USER" ] && DIR="/var/run/screen/S-$USER" || DIR="$DATA" t2=`date +%s` for i in "read" "write"; do @@ -50,20 +63,21 @@ for i in "read" "write"; do if [ $t2 -le $t1 ]; then rate=0 else - x1=`cat "$cache"` 2>/dev/null || tx1=0 + [ -r "$cache" ] && read x1 < "$cache" || x1=0 + read a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 other < "/sys/block/$disk/stat" if [ "$i" = "read" ]; then symbol="$ICON_RD" - x2=`awk '{print $3}' /sys/block/$disk/stat` + x2="$a3" else symbol="$ICON_WR" - x2=`awk '{print $7}' /sys/block/$disk/stat` + x2="$a7" fi echo "$x2" > "$cache" - rate=`echo "$t1" "$t2" "$x1" "$x2" | awk '{printf "%.0f", ($4 - $3) / ($2 - $1) * 512 / 1024 }'` + rate=$((($x2-$x1) / ($t2 - $t1) * 512 / 1024)) if [ "$rate" -lt 0 ]; then rate=0 elif [ "$rate" -gt 1024 ]; then - rate=`echo "$rate" | awk '{printf "%.1f", $1/1024}'` + fpdiv "$rate" 1024 1 unit="MB/s" fi fi diff --git a/usr/lib/byobu/load_average b/usr/lib/byobu/load_average index afd3da3e..8341ac2e 100755 --- a/usr/lib/byobu/load_average +++ b/usr/lib/byobu/load_average @@ -24,5 +24,5 @@ if [ "$1" = "--detail" ]; then cat /proc/loadavg exit 0 fi - -color Y k; printf "%s" "$(awk '{print $1}' /proc/loadavg)"; color -- +read one five fifteen other < /proc/loadavg +color Y k; printf "$one"; color -- diff --git a/usr/lib/byobu/network b/usr/lib/byobu/network index 4e8348b1..15afdfbc 100755 --- a/usr/lib/byobu/network +++ b/usr/lib/byobu/network @@ -27,7 +27,8 @@ color 2>/dev/null || color() { true; } if [ -n "$MONITORED_NETWORK" ]; then interface="$MONITORED_NETWORK" else - interface=`tail -n1 /proc/net/route | awk '{print $1}'` + # get the last interface listed in /proc/net/route + while read cn other; do interface=$cn; done < /proc/net/route fi if [ "$1" = "--detail" ]; then @@ -48,24 +49,27 @@ for i in up down; do if [ $t2 -le $t1 ]; then rate=0 else - x1=`cat "$cache"` 2>/dev/null || tx1=0 - if [ "$i" = "up" ]; then - x2=`grep -m1 "\b$interface:" /proc/net/dev | sed "s/^.*://" | awk '{print $9}'` - else - x2=`grep -m1 "\b$interface:" /proc/net/dev | sed "s/^.*://" | awk '{print $1}'` - fi + [ -r "$cache" ] && read x1 < "$cache" || tx1=0 + while read iface rbytes rpackets rerrs rdrop rfifo rframe rcompressed rmulticast tbytes tpackets terrs tdrop tfifo tcolls tcarrier tcompressed; do + if [ "$iface" = "${interface}:" ]; then + [ "$i" = "up" ] && x2=${tbytes} || x2=${rbytes} + break; + fi + done < /proc/net/dev echo "$x2" > "$cache" - rate=`echo "$t1" "$t2" "$x1" "$x2" | awk '{printf "%.0f", ($4 - $3) / ($2 - $1) / 1024 }'` + rate=$((($x2 - $x1) / ($t2 - $t1) / 1024)) if [ "$rate" -lt 0 ]; then rate=0 fi case "$NETWORK_UNITS" in bytes) if [ "$rate" -gt 1048576 ]; then - rate=`echo "$rate" | awk '{printf "%.1f", $1/1048576}'` + fpdiv "$rate" 1048576 1 + rate=${_RET} unit="GB/s" elif [ "$rate" -gt 1024 ]; then - rate=`echo "$rate" | awk '{printf "%.1f", $1/1024}'` + fpdiv "$rate" 1024 1 + rate=${_RET} unit="MB/s" else unit="kB/s" @@ -73,13 +77,15 @@ for i in up down; do ;; *) # Default to bps - rate=`echo "$rate" | awk '{printf "%.0f", $1*8}'` + rate=$(($rate*8)) # Why 1000 and not 1024? http://en.wikipedia.org/wiki/Data_rate_units if [ "$rate" -gt 1000000 ]; then - rate=`echo "$rate" | awk '{printf "%.1f", $1/1000000}'` + fpdiv "$rate" 1000000 1 + rate=${_RET} unit="Gbps" elif [ "$rate" -gt 1000 ]; then - rate=`echo "$rate" | awk '{printf "%.1f", $1/1000}'` + fpdiv "$rate" 1000 1 + rate=${_RET} unit="Mbps" fi ;; diff --git a/usr/lib/byobu/uptime b/usr/lib/byobu/uptime index 35ba6ca4..3de0c69d 100755 --- a/usr/lib/byobu/uptime +++ b/usr/lib/byobu/uptime @@ -28,15 +28,17 @@ if [ "$1" = "--detail" ]; then exit 0 fi -u=$(sed "s/\..*$//" /proc/uptime) +read u idle < /proc/uptime +u=${u%.*} color w b if [ "$u" -gt 86400 ]; then - echo "$u" | awk '{printf "%dd%dh", $1 / 86400, ($1 % 86400)/3600 }' + str="$(($u / 86400))d%$((($u % 86400) / 3600))h" elif [ "$u" -gt 3600 ]; then - echo "$u" | awk '{printf "%dh%dm", $1 / 3600, ($1 % 3600 )/60}' + str="$(($u / 3600))h$((($u % 3600) / 60))m" elif [ "$u" -gt 60 ]; then - echo "$u" | awk '{printf "%dm", $1 / 60 }' + str="$(($u / 60))m" else - printf "%ds" "$u" + str="${u}s" fi +printf "%s" "${str}" color -- diff --git a/usr/lib/byobu/wifi_quality b/usr/lib/byobu/wifi_quality index 7622e29d..e31007b6 100755 --- a/usr/lib/byobu/wifi_quality +++ b/usr/lib/byobu/wifi_quality @@ -26,14 +26,22 @@ if [ "$1" = "--detail" ]; then exit 0 fi -iwconfig=`/sbin/iwconfig $MONITORED_NETWORK 2>/dev/null` -bitrate=`echo "$iwconfig" | grep "Bit Rate." | sed -e "s/^.*Bit Rate.//" -e "s/ .*$//g"` +# iwconfig is expected to output lines like: +# Bit Rate=54 Mb/s Tx-Power=15 dBm +# Link Quality=60/70 Signal level=-50 dBm +# the awk below tokenizes the output and prints shell evalable results +out=`iwconfig $MONITORED_NETWORK 2>/dev/null | + awk '$0 ~ /[ ]*Link Quality./ { + sub(/.*=/,"",$2); split($2,a,"/"); + printf "quality=%.0f\n", 100*a[1]/a[2] }; + $0 ~ /[ ]*Bit Rate/ { sub(/.*=/,"",$2); printf("bitrate=%s\n", $2); } + '` +eval "$out" + [ -z "$bitrate" ] && bitrate="0" -quality=`echo "$iwconfig" | grep "Link Quality." | sed -e "s/^.*Link Quality.//" -e "s/ .*$//g"` + if [ -z "$quality" ] || [ "$quality" = "0" ]; then quality="0" -else - quality=`echo "$quality" | awk -F/ '{printf "%.0f", 100*$1/$2}'` fi [ "$quality" = "0" ] && exit 0