xrandr --output LVDS-1 --brightness $(bc -l <<<"$(sed 's/Brightness: //' <<<$(xrandr --prop --verbose | grep Brightness)) $(if [ "$1" = "+" ];then echo +;else echo -;fi) 0.1")

I currently have this code set up to a keyboard shortcut in XFCE on my Arch system, and it works great to adjust brightness up or down 0.1 notches. Only problem is, it's slow enough to take a second or so to execute, and pressing multiple times is worse and can slow the whole computer a bit.

How would you improve the code? (I'm pretty new to shell scripting, so I'm also partly asking this to see the process by which code I write cold be optimized.)

EDIT: Okay, so I followed drewbenn's suggestion of profiling and got this:
time xrandr -q --verbose > /dev/null
real 0m1.746s
user 0m0.007s
sys 0m0.000s

The query, then, was the biggest issue. I changed it so that it would store the current brightness level in a file somewhere and the shortcut keys would run the following code:

val=$(cat ~/.bright_key_folder/lvl)
if ( [ "$1" == "+" ] && [[ $(bc -l  ~/.bright_key_folder/lvl
    xrandr --output LVDS-1 --brightness $(cat ~/.bright_key_folder/lvl)
elif ( [ "$1" == "-" ] && [[ $(bc -l  0") == 1 ]] )
    bc -l  ~/.bright_key_folder/lvl
    xrandr --output LVDS-1 --brightness $(cat ~/.bright_key_folder/lvl)

Then on startup it resets brightness and the file value both to 1.

  • Try xbacklight. It may or may not work for (I think they go through different mechanisms and not all drivers support both). It may or may not be faster. – Gilles May 11 '16 at 23:53

If code is already working but running too slowly, the next step is to start profiling. When shell scripting, you can use time (try help time to see its help page) to see how long each command takes to run.

I think bc should be very fast; sed against one line should also be very fast; and grep should be pretty quick, too, so I decided to try profiling the two xrandr commands on my system. I just wanted some quick estimates, so I tried executing the commands individually (instead of, say, wrapping them in a script to run them dozens of times to get an average):

$ time xrandr --prop --verbose >/dev/null

real    0m0.428s
user    0m0.004s
sys     0m0.004s
$ time xrandr --output LVDS1 --brightness 0.9

real    0m0.117s
user    0m0.000s
sys     0m0.008s

If you get similar results, your query might be what's taking the most time.

  • Thanks! The query was indeed taking the most time -- sometimes a full 2 seconds -- so I stored the value elsewhere. time's a useful command, glad to have learned it. – CalvinSchwa May 15 '16 at 21:38

Well, for one thing, you are running three separate external programs when one would be enough. You could do all the parsing and arithmetic in awk for example:

xrandr --output LVDS-1 --brightness $(xrandr --prop --verbose | 
    awk "/Brightness:/{print \$2 $1 0.1; exit}")

The exit in the awk script ensures that it doesn't need to parse the whole output of xrandr --prop --verbose and exits after the first match for Brightness:. Then, since the awk command is in double quotes, the $1 is expanded to the argument given to the script while the \$2 refers to the second field in awk because it is escaped.

You could also try using a faster shell. If your default is bash, try running the script with dash.

  • I accepted the other answer because it was what ended up solving the problem for me, but this was what I was looking for initially and what others who see the problem will find. Thank you for responding -- once I've enough reputation I'll be sure to come back and at least +1 the answer. – CalvinSchwa May 15 '16 at 21:41

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.