-
Notifications
You must be signed in to change notification settings - Fork 930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: optimize performance of waybar cpuinfo and gpuinfo modules #952
base: main
Are you sure you want to change the base?
Changes from all commits
74d64af
bc4cca3
0c360f5
bd0a4d9
17d7cd3
24c4796
8ff0036
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,35 +1,80 @@ | ||||||||||||||
#!/usr/bin/env sh | ||||||||||||||
#!/bin/bash | ||||||||||||||
|
||||||||||||||
# CPU model | ||||||||||||||
model=$(lscpu | awk -F ':' '/Model name/ {sub(/^ *| *$/,"",$2); print $2}' | awk '{NF-=3}1') | ||||||||||||||
|
||||||||||||||
# CPU utilization | ||||||||||||||
utilization=$(top -bn1 | awk '/^%Cpu/ {print 100 - $8}') | ||||||||||||||
# Thee shalt find the greatest one, | ||||||||||||||
# He who not more than the chosen one | ||||||||||||||
map_floor() { | ||||||||||||||
|
||||||||||||||
# Clock speed | ||||||||||||||
freqlist=$(cat /proc/cpuinfo | grep "cpu MHz" | awk '{ print $4 }') | ||||||||||||||
maxfreq=$(lscpu | grep "CPU max MHz" | awk -F: '{ print $2}' | sed -e 's/ //g' -e 's/\.[0-9]*//g') | ||||||||||||||
frequency=$(echo $freqlist | tr ' ' '\n' | awk "{ sum+=\$1 } END {printf \"%.0f/$maxfreq MHz\", sum/NR}") | ||||||||||||||
# From the depths of the string, words arise, | ||||||||||||||
# Keys in pairs, a treasure in disguise. | ||||||||||||||
IFS=', ' read -r -a pairs <<< "$1" | ||||||||||||||
|
||||||||||||||
# CPU temp | ||||||||||||||
temp=$(sensors | awk '/Package id 0/ {print $4}' | awk -F '[+.]' '{print $2}') | ||||||||||||||
if [ -z "$temp" ]; then | ||||||||||||||
temp=$(sensors | awk '/Tctl/ {print $2}' | tr -d '+°C') | ||||||||||||||
fi | ||||||||||||||
if [ -z "$temp" ]; then | ||||||||||||||
temp="N/A" | ||||||||||||||
fi | ||||||||||||||
# If the final token stands alone and bold, | ||||||||||||||
# Declare it the default, its worth untold. | ||||||||||||||
if [[ ${pairs[-1]} != *":"* ]]; then | ||||||||||||||
def_val="${pairs[-1]}" | ||||||||||||||
unset 'pairs[${#pairs[@]}-1]' | ||||||||||||||
fi | ||||||||||||||
|
||||||||||||||
# Scans the map, a peak it seeks, | ||||||||||||||
# The highest passed, the value speaks. | ||||||||||||||
for pair in "${pairs[@]}"; do | ||||||||||||||
IFS=':' read -r key value <<< "$pair" | ||||||||||||||
|
||||||||||||||
# Behold! Thou holds the secrets they seek, | ||||||||||||||
# Declare it and silence the whispers unique. | ||||||||||||||
if [ ${2%%.*} -gt $key ]; then | ||||||||||||||
echo "$value" | ||||||||||||||
return | ||||||||||||||
fi | ||||||||||||||
done | ||||||||||||||
|
||||||||||||||
# map icons | ||||||||||||||
set_ico="{\"thermo\":{\"0\":\"\",\"45\":\"\",\"65\":\"\",\"85\":\"\"},\"emoji\":{\"0\":\"❄\",\"45\":\"☁\",\"65\":\"\",\"85\":\"\"},\"util\":{\"0\":\"\",\"30\":\"\",\"60\":\"\",\"90\":\"\"}}" | ||||||||||||||
eval_ico() { | ||||||||||||||
map_ico=$(echo "${set_ico}" | jq -r --arg aky "$1" --argjson avl "$2" '.[$aky] | keys_unsorted | map(tonumber) | map(select(. <= $avl)) | max') | ||||||||||||||
echo "${set_ico}" | jq -r --arg aky "$1" --arg avl "$map_ico" '.[$aky] | .[$avl]' | ||||||||||||||
# On this lonely shore, where silence dwells | ||||||||||||||
# Even the waves, echoes words unheard | ||||||||||||||
[ -n "$def_val" ] && echo $def_val || echo " " | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
thermo=$(eval_ico thermo $temp) | ||||||||||||||
emoji=$(eval_ico emoji $temp) | ||||||||||||||
speedo=$(eval_ico util $utilization) | ||||||||||||||
# Define glyphs | ||||||||||||||
if [[ $NO_EMOJI -eq 1 ]]; then | ||||||||||||||
temp_lv="85:, 65:, 45:☁, ❄" | ||||||||||||||
else | ||||||||||||||
temp_lv="85:🌋, 65:🔥, 45:☁️, ❄️" | ||||||||||||||
fi | ||||||||||||||
util_lv="90:, 60:, 30:, " | ||||||||||||||
|
||||||||||||||
# Get static CPU information | ||||||||||||||
model=$(lscpu | awk -F': ' '/Model name/ {gsub(/^ *| *$| CPU.*/,"",$2); print $2}') | ||||||||||||||
maxfreq=$(lscpu | awk '/CPU max MHz/ { sub(/\..*/,"",$4); print $4}') | ||||||||||||||
|
||||||||||||||
# Get CPU stat | ||||||||||||||
statFile=$(cat /proc/stat | head -1) | ||||||||||||||
prevStat=$(awk '{print $2+$3+$4+$6+$7+$8 }' <<< $statFile) | ||||||||||||||
prevIdle=$(awk '{print $5 }' <<< $statFile) | ||||||||||||||
|
||||||||||||||
while true; do | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the loop? its not recommended to run this as a daemon process. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It can be made to execute once in every 5s instead by saving the prev statistics to a temp file. However, I don't see why it is not recommended to run it as a daemon as re-executing the script has to deal with unnecessary system calls, read-writes and re-interpreting the script once in every 5s. Also, it is not going to save cpu time on the scheduler as it has to deal with the sleep syscall from the script otherwise the same from the waybar. It is also noted that the waybar builtin modules which requires updates on periodic intervals (memory, cpu_usage) are running on separate daemon threads. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh my bad I missed it, you did mention it, but it was too long so I didn't read :( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per the hyprdots/Configs/.local/share/bin/wbarconfgen.sh Lines 125 to 130 in 8369bed
According the above snippet, when you switch the mode, the waybar and its entire process tree will be killed, including our poor little daemon. Sorry for the late reply, was little too busy these days. |
||||||||||||||
# Get CPU stat | ||||||||||||||
statFile=$(cat /proc/stat | head -1) | ||||||||||||||
currStat=$(awk '{print $2+$3+$4+$6+$7+$8 }' <<< $statFile) | ||||||||||||||
currIdle=$(awk '{print $5 }' <<< $statFile) | ||||||||||||||
diffStat=$((currStat-prevStat)) | ||||||||||||||
diffIdle=$((currIdle-prevIdle)) | ||||||||||||||
|
||||||||||||||
# Get dynamic CPU information | ||||||||||||||
utilization=$(awk -v stat="$diffStat" -v idle="$diffIdle" 'BEGIN {printf "%.1f", (stat/(stat+idle))*100}') | ||||||||||||||
temperature=$(sensors | awk -F': ' '/Package id 0|Tctl/ { gsub(/^ *\+?|\..*/,"",$2); print $2; f=1; exit} END { if (!f) print "N/A"; }') | ||||||||||||||
frequency=$(cat /proc/cpuinfo | awk '/cpu MHz/{ sum+=$4; c+=1 } END { printf "%.0f", sum/c }') | ||||||||||||||
|
||||||||||||||
# Generate glyphs | ||||||||||||||
icons=$(echo "$(map_floor "$util_lv" $utilization)$(map_floor "$temp_lv" $temperature)") | ||||||||||||||
speedo=$(echo ${icons:0:1}) | ||||||||||||||
thermo=$(echo ${icons:1:1}) | ||||||||||||||
emoji=$(echo ${icons:2}) | ||||||||||||||
|
||||||||||||||
# Print the output | ||||||||||||||
echo "{\"text\":\"$thermo $temperature°C\", \"tooltip\":\"$model\n$thermo Temperature: $temperature°C $emoji\n$speedo Utilization: $utilization%\n Clock Speed: $frequency/$maxfreq MHz\"}" | ||||||||||||||
|
||||||||||||||
# Print cpu info (json) | ||||||||||||||
echo "{\"text\":\"${thermo} ${temp}°C\", \"tooltip\":\"${model}\n${thermo} Temperature: ${temp}°C ${emoji}\n${speedo} Utilization: ${utilization}%\n Clock Speed: ${frequency}\"}" | ||||||||||||||
# Store state and sleep | ||||||||||||||
prevStat=$currStat | ||||||||||||||
prevIdle=$currIdle | ||||||||||||||
sleep 5 | ||||||||||||||
done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lscpu
respectsLANG
and thus requiresen_us
for this to work.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, good find. I'll add this on the next commit.