You are not logged in.

#1 2016-02-26 05:12:27

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Efficiency of bash script (lemonbar statusline)

Hi!

Would somebody wish to evaluate efficiency of my statusline script? It is a bash script that pipes information to lemonbar, I call it limepanel. Previously I used conky-cli to pipe the same information, but I found that doing the samw with bash was more responsive and used less resources.

Here is the script:
https://github.com/Chrysostomus/limepan … /limepanel

This is how it looks:
http://i.imgur.com/8OudMMI.png
And this is the part that I wish to improve on:

interface_up=$(ip link show | awk '/state UP/ {print substr($2, 1, length($2)-1)}')
is_wifi()
{
	iwconfig $interface_up >/dev/null 2>&1
}
sigStrength()
{
  signalStrength=$(awk 'NR==3 { print substr($3, 1, length($3)-1)}' /proc/net/wireless)
	final=$(echo $isEthernet | awk '{print $1}')

	if ! is_wifi;
	then
        echo %{F$COLOR_FOCUSED_DESKTOP_FG}" "
        elif [ "$signalStrength" -gt 64 ]
        then
                echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅▇"
        elif [ "$signalStrength" -lt 65 ] && [ "$signalStrength" -gt 39 ]
        then
                echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅"$DARKGREY"▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        elif [ "$signalStrength" -lt 40 ]
        then
                echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃"$DARKGREY"▅▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        else
                echo $DARKGREY""%{F$COLOR_FOCUSED_DESKTOP_FG}
        fi
}

battery() {
	BATC=$(cat /sys/class/power_supply/BAT1/capacity)
	BATS=$(cat /sys/class/power_supply/BAT1/status)
	if [[ $BATS == "Charging" ]]; then
		echo " $BATC%"
	elif [ $BATC -gt 80 ]
	then
		echo " $BATC%"
	elif [ $BATC -gt 50 ]
	then
		echo " $BATC%"
	else 
		echo "$RED $BATC%%{F$COLOR_FOCUSED_DESKTOP_FG}"
	fi
}

clock() {
    date '+%H:%M'
}

status()
{
while	:; do
	echo "C%{A:networkmenuplacer.sh ; nmcli_dmenu:}$(sigStrength)%{A} %{A:dbright:}$(battery)%{A}  $(clock)"
	sleep $update_interval
done
}

Currently the script uses about 2mb (+2mb for lemonbar) and starts 5 processes (+xtitle +lemonbar). Any ways to slim this down? I wish to use as little ram and cpu as possible.

Last edited by jasonwryan (2016-02-26 05:19:43)


The difference between reality and fiction is that fiction has to make sense.

Offline

#2 2016-02-26 05:23:21

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,424
Website

Re: Efficiency of bash script (lemonbar statusline)

Read the Forum Etiquette and only post thumbnails http://wiki.archlinux.org/index.php/For … s_and_code

`[[` is faster than `[` and case statements are faster than `if.. then`.


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#3 2016-02-26 07:10:44

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Thank you!

Posting a full screenshot was an accident, sorry about.


The difference between reality and fiction is that fiction has to make sense.

Offline

#4 2016-02-26 08:06:13

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Does this seem better?

sigStrength()
{
  signalStrength=$(awk 'NR==3 { print substr($3, 1, length($3)-1)}' /proc/net/wireless)
	
	if ! is_wifi;
	then
        echo %{F$COLOR_FOCUSED_DESKTOP_FG}" "
        
        else
        	case $signalStrength in
        	100|[6-9]*) echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅▇"
        		;;
        	[4-5]*) echo echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅"$DARKGREY"▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        		;;
        	[1-3]*) echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃"$DARKGREY"▅▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        		;;
        	*) echo $DARKGREY" "
        		
        		;;
        	esac 
    fi
}

battery() {
    BATC=$(cat /sys/class/power_supply/BAT1/capacity)
    BATS=$(cat /sys/class/power_supply/BAT1/status)
	if [[ $BATS == "Charging" ]]; then
		echo " $BATC%"
	else 
		case $BATC in
		100|[7-9]*) echo " $BATC%"
			
			;;
		[4-6]*) echo " $BATC%"
			
			;;
		*) echo "$RED $BATC%%{F$COLOR_FOCUSED_DESKTOP_FG}"
			
			;;
		esac
	fi
}

Is case statement just faster than nested if statements, or also faster than if statement in general? What I mean is this: is a single case statement with 2 options faster than single if statement?

Last edited by Chrysostomus (2016-02-26 08:50:37)


The difference between reality and fiction is that fiction has to make sense.

Offline

#5 2016-02-26 08:47:26

ayekat
Member
Registered: 2011-01-17
Posts: 1,590

Re: Efficiency of bash script (lemonbar statusline)

What happens if $signalStrengh < 10? Try instead

100|[6-9]?) echo ... ;;
[4-5]?) echo ... ;;
[1-3]?) echo ... ;;
*) echo .... ;;

pkgshackscfgblag

Offline

#6 2016-02-26 08:51:25

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Thanks!


The difference between reality and fiction is that fiction has to make sense.

Offline

#7 2016-02-26 09:21:11

brebs
Member
Registered: 2007-04-03
Posts: 3,742

Re: Efficiency of bash script (lemonbar statusline)

Dash (being lightweight), and especially busybox's "ash" (because the busybox executable has many commands commands built-in, rather than having to call external programs), will be noticeably faster than BASH.

Quote your variables!

Edit: As a quick example of what *NOT* to do:

cd /etc
a="hi ; $(ls)"
echo $a

Last edited by brebs (2016-02-26 09:29:09)

Offline

#8 2016-02-26 10:32:11

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Okay, moving to dash reduced ram usage by about 70%. Nit bad advice. Thanks!


The difference between reality and fiction is that fiction has to make sense.

Offline

#9 2016-02-26 14:22:24

alphaniner
Member
From: Ancapistan
Registered: 2010-07-12
Posts: 2,810

Re: Efficiency of bash script (lemonbar statusline)

jasonwryan wrote:

`[[` is faster than `[`

Do you know if this holds true for eg. [[ 'foobar' = 'foobar' ]], since `[[` does pattern matching whereas `[` does simple string comparison?

$ set -x
$ [ 'foobar' = 'foobar' ]
+ '[' foobar = foobar ']'
$ [[ 'foobar' = 'foobar' ]]
+ [[ foobar = \f\o\o\b\a\r ]]

Edit: I did a little test and it seems `[[` is faster even when supplied with long identical strings. Should I not be surprised by this?

PS Sorry for hijacking.

Last edited by alphaniner (2016-02-26 14:35:28)


But whether the Constitution really be one thing, or another, this much is certain - that it has either authorized such a government as we have had, or has been powerless to prevent it. In either case, it is unfit to exist.
-Lysander Spooner

Offline

#10 2016-02-26 16:12:50

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

No worries, the data was interesting for me too. Dash only has [ ] though.


The difference between reality and fiction is that fiction has to make sense.

Offline

#11 2016-02-26 18:57:42

alphaniner
Member
From: Ancapistan
Registered: 2010-07-12
Posts: 2,810

Re: Efficiency of bash script (lemonbar statusline)

Well, that's probably the explanation after all. I had forgotten that `[` is a binary rather than a bash builtin like `[[`.

Edit: Oops, I used 'which' when I should have used 'type'. As I originally thought, `[` is also a bash builtin. I'll shut up now. smile

Last edited by alphaniner (2016-02-26 19:13:35)


But whether the Constitution really be one thing, or another, this much is certain - that it has either authorized such a government as we have had, or has been powerless to prevent it. In either case, it is unfit to exist.
-Lysander Spooner

Offline

#12 2016-02-26 19:16:28

papajoke
Member
From: france
Registered: 2014-10-10
Posts: 40

Re: Efficiency of bash script (lemonbar statusline)

hi,

and in battery()  if [ $BATS == "Charging" ] 2> /dev/null; is not good, just

if [ "$BATS" = "Charging" ]; then

-----------
and evaluate $signalStrength before test is_wifi() no ; ony if is_wifi() == ok

-------------------

for $signalStrength, with this case substr in awk is not required

Last edited by papajoke (2016-02-26 19:22:34)


lts - zsh - Kde - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau

Offline

#13 2016-02-26 19:42:51

alphaniner
Member
From: Ancapistan
Registered: 2010-07-12
Posts: 2,810

Re: Efficiency of bash script (lemonbar statusline)

To generalize on what papajoke said, always quote variables inside [ ]:

$ unset a
$ [ $a = 'foo' ] && echo 1
dash: 2: [: =: unexpected operator
$ [ "$a" = 'foo' ] && echo 1
$ [ -n $a ] && echo 1     # -n should not evaluate true with an unset var!
1
$ [ -n "$a" ] && echo 1

Numerical comparisons with [ ] are even worse IIRC.


But whether the Constitution really be one thing, or another, this much is certain - that it has either authorized such a government as we have had, or has been powerless to prevent it. In either case, it is unfit to exist.
-Lysander Spooner

Offline

#14 2016-02-27 02:05:46

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Thanks all for input!

Here is the current script:

#! /bin/dash
#panel script for bspwm using i3 style workspace indicator

#set height and font if unset 

if ! [ -f "$HOME/.limepanelrc" ]; then
	cat > $HOME/.limepanelrc <<EOL
panel_height='25'
mainfont='-zevv-*-*-*-*-*-20-*-*-*-*-*-*-*'
iconfont="-*-ionicons-medium-r-normal-*-25-*-*-*-p-*-*-1"
powerlinefont='dejavu sans mono for Powerline :size=12 :style=regular'
gap=15
COLOR_FOCUSED_DESKTOP_FG='#FF1ABB9B'
COLOR_FOCUSED_DESKTOP_BG="#FF000000"
COLOR_DESKTOP_FG='#FFF6F9FF'
COLOR_DESKTOP_BG="#FF000000"
update_interval=3
EOL
fi
export PANEL_FIFO="/tmp/panel-fifo"
grep -q update_interval $HOME/.limepanelrc || echo 'update_interval="3"' >> $HOME/.limepanelrc

. $HOME/.limepanelrc

# Kill any panel processes older than us, instead of bailing like the example
# does. That caused one too many panel-less boots for me.

while [ $(pgrep -cx limepanel) -gt 1 -o $(pgrep -cx lemonbar) -gt 1 ] ; do
	pkill -ox -9 limepanel
	pkill -ox -9 lemonbar
	killall -9 stalonetray
	killall -9 xtitle
done

#trap 'trap - TERM; kill 0' INT TERM QUIT EXIT

bspc config top_padding $((panel_height-gap))

menu="%{A:BspwmWindowMenu:} %{A}%{A:BspwmDesktopMenu:} %{A}"
logo="%{A:dmainmenu.sh &disown:}  %{A}"
DARKGREY="%{F#FF707880}"
RED="%{F#FFA54242}"
interface_up=$(ip link show | awk '/state UP/ {print substr($2, 1, length($2)-1)}')
is_wifi()
{
	iwconfig $interface_up >/dev/null 2>&1
}
sigStrength()
{
	if ! is_wifi;
	then
        echo %{F$COLOR_FOCUSED_DESKTOP_FG}" "
        
        else
        signalStrength=$(awk 'NR==3 {print $3}' /proc/net/wireless)
        	case $signalStrength in
        	[6-9]*) echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅▇"
        		;;
        	[4-5]*) echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃▅"$DARKGREY"▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        		;;
        	[1-3]*) echo %{F$COLOR_FOCUSED_DESKTOP_FG}"▁▃"$DARKGREY"▅▇"%{F$COLOR_FOCUSED_DESKTOP_FG}
        		;;
        	*) echo $DARKGREY" "%{F$COLOR_FOCUSED_DESKTOP_FG}
        		
        		;;
        	esac 
    fi
}

battery() {
    BATC=$(cat /sys/class/power_supply/BAT1/capacity)
    BATS=$(cat /sys/class/power_supply/BAT1/status)
	if [ "$BATS" = "Charging" ]; then
		echo " $BATC%"
	else 
		case $BATC in
		100|[7-9]*) echo " $BATC%"
			
			;;
		[4-6]*) echo " $BATC%"
			
			;;
		*) echo "$RED $BATC%%{F$COLOR_FOCUSED_DESKTOP_FG}"
			
			;;
		esac
	fi
}

clock() {
    date '+%H:%M'
}

status()
{
if [ -e /sys/class/power_supply/BAT1/ ]; then
	while	:; do
	echo "C%{A:networkmenuplacer.sh ; nmcli_dmenu:}$(sigStrength)%{A} %{A:dbright:}$(battery)%{A}  $(clock)"
	sleep $update_interval
done	
else
	while	:; do
	echo "C%{A:networkmenuplacer.sh ; nmcli_dmenu:}$(sigStrength)%{A}  $(clock)"
	sleep $update_interval
done
fi

}

lime() {
 while read -r line ; do
    case $line in
        T*)
            title="%{A:MonocleSwitcher:}${line#?}%{A}"
            ;;
	C*)
            conky_infos="%{F$COLOR_FOCUSED_DESKTOP_FG}${line#?}"
            ;;
	V*)
            volume_infos="${RA}%{F$COLOR_FOCUSED_DESKTOP_FG} ${line#?} "
            ;;
        W*)
            # bspwm internal state
            desktops=""
            IFS=':'
            set -- ${line#?}
            while [ $# -gt 0 ] ; do
                item=$1
                name=${item#?}
                case $item in
                    # always show focused desktops
                    O*|F*|U*)
                        desktops="${desktops}%{F$COLOR_FOCUSED_DESKTOP_FG}%{B$COLOR_FOCUSED_DESKTOP_BG}%{U"$COLOR_FOCUSED_DESKTOP_FG"}%{+u}${name}%{-u} %{B-}%{F-}"
                        ;;
                    # show used unfocused (hide free unused)
                    o*|u*)#f*
                        desktops="${desktops}%{F$COLOR_DESKTOP_FG}%{B$COLOR_DESKTOP_BG}%{A:bspc desktop -f ${name}:}${name}%{A}%{B-} %{F-}"
                        ;;
                    L*)
                    # layout
                        layout="%{A:bspc desktop -l next:}$wm_infos${name}%{B-}%{F-}%{A}"
                        ;;
                esac
                shift
            done
            ;;
    esac
    printf "%s\n" "%{l}${logo}${desktops}${layout}%{F$COLOR_DESKTOP_FG}%{c}${title}%{r}%{F$COLOR_FOCUSED_DESKTOP_FG}$menu$volume_infos${conky_infos}"
 done
}

# Rename monitors to numbers
i=1
for monitor in $(bspc query -M); do
    bspc monitor $monitor \
        -n "$i" \
    let i++
done
unset i


for i in $(bspc query -M); do
	# Remove old fifos and create new ones
	[ -e "$PANEL_FIFO$i" ] && rm "$PANEL_FIFO$i"
	mkfifo "$PANEL_FIFO$i"
	# Wm infos of specific monitor
	bspc subscribe |\
        grep -oE "[Mm]$i[^TM]*[TML]" --line-buffered |\
        while read line; do echo W$line; done \
            > "$PANEL_FIFO$i" &
	# Title
	xtitle -t 80 -sf 'T%s' > "$PANEL_FIFO$i" &
	# conky infos
#	[ $(pgrep -cx conky) -lt 1 ] && conky -c ~/.config/bspwm/panel/conkyrc > /tmp/panel-fifo$i &
	#status
	status > /tmp/panel-fifo$i &
	# Volume-infos
	volume_status.sh &
	# Pipe all the info to lemonbar
	cat $PANEL_FIFO$i $PANEL_FIFO \
		| lime \
		| lemonbar \
		-g x$panel_height \
		-f "$mainfont" -o -1 \
		-f "$iconfont" -o 0 \
		-o -3 -f "$powerlinefont" \
		-F $COLOR_FOCUSED_DESKTOP_FG \
		-B $COLOR_DESKTOP_BG \
		| while read line; do eval "$line"; done &
done
wait

The difference between reality and fiction is that fiction has to make sense.

Offline

#15 2016-02-27 09:10:21

brebs
Member
Registered: 2007-04-03
Posts: 3,742

Re: Efficiency of bash script (lemonbar statusline)

You've still got numerous instances of unquoted variables, e.g.:

cat > $HOME/.limepanelrc
cat $PANEL_FIFO$i $PANEL_FIFO
iwconfig $interface_up

Are you *trying* to shoot yourself in the foot? Quote your variables! Lest you end up *running code* which is totally different to what you thought it would run.

Offline

#16 2016-02-27 09:36:50

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Thought erraneously it mattered only within [ ]. Thanks for clarification!


The difference between reality and fiction is that fiction has to make sense.

Offline

#17 2016-02-27 16:07:22

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Hmm... either adding more quotes to variables or moving signal strength test inside the if sentence made it so that panel falsely shows ethernet connected symbol if panel is autostarted. My guess is the latter. Wifi-indicator works if I run it manually, adding delay to autostarting panel makes no difference. Need to figure this out...


The difference between reality and fiction is that fiction has to make sense.

Offline

#18 2016-02-27 18:28:22

papajoke
Member
From: france
Registered: 2014-10-10
Posts: 40

Re: Efficiency of bash script (lemonbar statusline)

I think $interface_up is evaluated only once at the start of the script. it should be in the loop and more particularly in is_wifi() function.
In functions no variable is declared locally and not initialized; can be a problem with your loops.


lts - zsh - Kde - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau

Offline

#19 2016-02-28 07:35:22

Chrysostomus
Member
Registered: 2015-09-13
Posts: 64
Website

Re: Efficiency of bash script (lemonbar statusline)

Thanks, that was it!
I imagined that variable is evaluated every time it is accessed, but it is not it seems. The actual behavior seems to be much more sensible.


The difference between reality and fiction is that fiction has to make sense.

Offline

Board footer

Powered by FluxBB