Search code examples
awkxfce

Using awk to gather network use from a single line in 2 files read at different times


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

Solution

  • 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
    }'