 |
Improve Linux performance
By Cameron Laird
2004-04-08
Reader Rating:

Two countdown examples
Performing a long computation while simultaneously keeping a user informed of its progress models an interesting problem in application design. It's an instance of concurrency, or "multitasking." Many developers believe concurrency demands elaborate mechanisms, and difficult threading code in particular, for a proper solution.
It's not true. The Resources section below lists an earlier developerWorks column in which I sketch the range of technologies involved in concurrency. What's more, simple concurrent programming has been available on essentially all UNIX hosts since at least 1988, which is when ksh standardized its "co-processes." If you save the ksh source in Listing 1, below, as ex1.ksh and then run it, you'll see a "countdown" -- "ten, nine, eight, etc." -- display, then the result of the ksh subprocess: "All done." In practice, you might use something like this for a long-running chemical calculation or database retrieval: launch the operation as a subprocess, but keep users informed about what's going on or how much time is left before completion. It only takes a couple of lines of source code to update the display.
Listing 1. ksh source code for example countdown display
(echo "This models a long-lasting process"; sleep 10;
echo "All done") |&
for ((i = 10; i > 0; i--))
do
printf "%2d seconds before completion ...\r" $i
sleep 1
done
read -p line; # Discard the title line.
read -p line
echo ""
echo "Output from the sub-process is '$line'."
"Real-time" information for your users requires no more than a modest amount of coding; even character-based applications can do it. If a graphical user interface (GUI) fits your situation better, that's also easy. Many toolkits build in "busy" or "waiting" or "progress" displays. If you don't already have one at hand, a few lines of Tk or another modern GUI toolkit will suffice to make a little "analogue" countdown clock face or progress bar. Here's an example "from scratch" that fits on a couple of pages:
Listing 2. Tk source code for example countdown display
proc countdown {seconds} {
init
countdown_kernel $seconds
}
proc countdown_kernel seconds {
hands $seconds
if !$seconds return
after 1000 [list countdown_kernel [incr seconds -1]]
}
proc draw_hand {angle decorations} {
eval .c create line $::size $::size [get_xy $angle] $decorations
}
proc end_coordinate difference {
set hand_length [expr $::size * .9]
return [expr $::size + $hand_length * $difference]
}
proc get_xy angle {
return [list [end_coordinate [expr sin($angle)]] \
[end_coordinate [expr -cos($angle)]]]
}
proc hands seconds {
catch {.c delete withtag hands}
set twopi 6.283185
set seconds_angle [expr $seconds * $twopi / 60.]
draw_hand $seconds_angle "-width 1 -tags hands"
set minutes_angle [expr $seconds_angle / 60.]
draw_hand $minutes_angle \
"-width 3 -capstyle projecting -tags hands"
}
proc init {} {
catch {destroy .c}
set ::size 30
set full_diameter [expr 2 * $::size]
pack [canvas .c -width $full_diameter -height $full_diameter]
set border 2
set diameter [expr 2 * $::size - $border]
.c create oval $border $border \
$diameter $diameter \
-fill white -outline black
}
countdown 10
This countdown shows a minute and second hand, as in Figure 1, with the same information content as the previous program.
Figure 1. Display of analogue countdown clock coded in Tk
Remember: information can substitute for functionality. The more your end users know about the internal state of your application, the less they'll require of you. You can solve many apparent performance problems just by teaching your programs to show what they're doing.
First published by IBM developerWorks
If you found this article interesting, you may want to read these as well:
|
| |
|
 |
|