6
\$\begingroup\$

For few days I'm thinking about making my code faster and using less CPU. This code is a statusbar that runs in a loop. I'm asking because there's a lot of perl and I'm wondering if it could be done better.

date=$( date +"%F %R" )

battery=$(acpi -b | perl -n -e '/(\S+),\s+([0-9]+\%),\s(\S*)\s/ && print $1," ",$2," [ ",$3," ]"')

RAM=$(free -m | perl -n -e '/Mem\:\s*([0-9]+)\s*([0-9]+).*/ && print "RAM: (",$2," / ",$1,")MB"')

VolumeLv=$(amixer get Master -c 1 | perl -n -e '/\[(.*)\%\]/ && print $1')

backLightLv=$(xbacklight | perl -n -e '/^([0-9]*)/ && print $1')
statusBacklight=$?
backLightBar=""
VolumeBar=""
Sign=":"
NoSign="."
for i in $(seq 1 2 100)
do
    if [ $i -gt $VolumeLv ]
    then
        VolumeBar=$(echo "$VolumeBar$NoSign")
    else
        VolumeBar=$(echo "$VolumeBar$Sign")
    fi
    if [ $statusBacklight -eq 0 ] && [ $i -gt $backLightLv ]
    then
        backLightBar=$(echo "$backLightBar$NoSign")
    else
        backLightBar=$(echo "$backLightBar$Sign")
    fi
done

ETHcards=""
for interface in $(iwconfig 2> /dev/null | perl -n -e '/^([a-zA-Z0-9]*)\s.*ESSID\:.*$/ && print $1,"\n"')
do
    IPANDMASK=$(ifconfig $interface | perl -n -e '/.*inet\ addr:([0-9\.]+).*Mask:([0-9\.]*)\s/ && print $1, "/", $2')
    MAC=$(ifconfig $interface | perl -n -e '/HWaddr\s+([a-f0-9\:]+)\s*/ && print $1')

    AP=$(iwconfig $interface 2>/dev/null | perl -n -e '/ESSID\:(\S*)/ && print $1')
    MODE=$(iwconfig $interface 2>/dev/null | perl -n -e '/Mode:(\S+)\s/ && print $1')

    ETHcards=$(echo "$ETHcards [ $interface ][ $MAC ][ $AP ][ $IPANDMASK ][ $MODE ]  //  ")
done
xsetroot -name "$date :: $battery;Volume: [$VolumeBar]$Mute $VolumeLv%    BackLight: [$backLightBar] $backLightLv%  //  $RAM  //  $ETHcards"
\$\endgroup\$
4
\$\begingroup\$

[...] there's a lot of perl and I'm wondering if it could be done better.

When you need to process the output of multiple commands, as in your example acpi, free, amixer, xbacklight, it's acceptable to call a perl for each.

The part needs improvement the most is the loop over the network interfaces, where you call iwconfig $interface and ifconfig $interface repeatedly to extract different part of the output into different variables. It would be better to rewrite this to call ifconfig and iwconfig just once per interface.

At a glance, it seems to me that everything you do with Perl, you could also do with awk, which might be slightly lighter.

If performance is extremely important, you could parse the output of all the commands with a single Perl or awk process, by carefully adding some marker lines in between commands, something like this:

marker='==== section ===='

{
    acpi -b
    echo $marker

    free -m
    echo $marker

    amixer get Master -c 1
    echo $marker

    xbacklight
    echo $marker

    iwconfig
    echo $marker

    ifconfig
} | perl -ne '...'

This way the number of processes spawned will be drastically reduced, and the performance difference will be noticeable.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.