To put this simply, I'm trying to build a genmon script that monitors network transfer using awk in a 1-liner to reduce CPU use.
What I'm aiming for is I'd like this script to update every 0.25 seconds.
What I have currently is a 4-line script:
PTXRX=( $(awk 'FNR==1' "/sys/class/net/${1}/statistics/tx_bytes" "/sys/class/net/${1}/statistics/rx_bytes") )
sleep 0.125
CTXRX=( $(awk 'FNR==1' "/sys/class/net/${1}/statistics/tx_bytes" "/sys/class/net/${1}/statistics/rx_bytes") )
awk -v ptx=${PTXRX[0]} -v prx=${PTXRX[1]} -v ctx=${CTXRX[0]} -v crx=${CTXRX[1]} 'BEGIN {printf "tx: %.2f KiB/s\nrx: %.2f KiB/s", (ctx-ptx)/512, (crx-prx)/512 }'
0.125
because the plugin needs time to display the update, so we're approximating in half the time and doubling the value (which isn't too far off).
sample data: (data expected in files)
tx_bytes: 284425478
rx_bytes: 3450790917
sleep 0.125
tx_bytes: 284426024
rx_bytes: 3450790917
The problem with this is it uses between 10-20% of my CPU...
How can I reduce this to just a single awk command and increase performance??
For those needing a visual to understand what this does, the result should display this:
tx: 0.00 KiB/s
rx: 0.00 KiB/s
Try this:
IFS= read -r ptx < "/sys/class/net/${1}/statistics/tx_bytes"
IFS= read -r prx < "/sys/class/net/${1}/statistics/rx_bytes"
sleep 0.125
IFS= read -r ctx < "/sys/class/net/${1}/statistics/tx_bytes"
IFS= read -r crx < "/sys/class/net/${1}/statistics/rx_bytes"
awk -v ptx="$ptx" -v prx="$prx" -v ctx="$ctx" -v crx="$crx" 'BEGIN {printf "tx: %.2f KiB/s\nrx: %.2f KiB/s\n", (ctx-ptx)/512, (crx-prx)/512 }'
If that doesn't help then you can't fix your performance problem in this code segment and you'll have to reconsider your approach of looping and calling commands every 0.125 secs.
If you're using bash you could replace the remaining call to awk with:
printf 'tx: %.2f KiB/s\nrx: %.2f KiB/s\n' $(( (ctx-ptx)/512 )) $(( (crx-prx)/512 ))
but it's still not going to make a significant difference.
One last thing you could try that MAY squeeze slightly better performance out of it (or it may even be worse but you can try it):
IFS= read -r ptx < "/sys/class/net/${1}/statistics/tx_bytes"
IFS= read -r prx < "/sys/class/net/${1}/statistics/rx_bytes"
sleep 0.125
awk -v ptx="$ptx" -v prx="$prx" -v tx_bytes="/sys/class/net/${1}/statistics/tx_bytes" -v rx_bytes="/sys/class/net/${1}/statistics/rx_bytes" 'BEGIN{
getline ctx < tx_bytes
getline crx < rx_bytes
printf "tx: %.2f KiB/s\nrx: %.2f KiB/s\n", (ctx-ptx)/512, (crx-prx)/512
}'