|
Perceptions and Performance
While there are many areas that impact user perception ( see User Perception performance tips for useful links and an idea of the range ), this article focuses on one relatively simple way to make program startup appear faster.
We've all written solid, optimized programs that meet project specifications and requirements, only to discover that users in the field complain that it's too slow. After investigation, it often turns out the real complaint is that "it takes so long to
load". While many programmers denigrate this type of complaint, user perception can be
as important as reality to the success of a project. What's a girl to do?
Interactive applications are characterized by activity at sporadic intervals. "Think time" and light loads like keyboard input provide opportunities to use otherwise idle CPU cycles to improve perceived performance. The technique discussed here makes use of an asynchronous, ready-as-needed style of processing to meet the goal at startup time: do the minimum work required to set up a form or input window, show it, and then complete the remaining tasks during idle time. The program could start a new thread for this processing, but a simpler and often ignored option is to just continue using the main thread after the AWT thread has been started.
One caution: To get the intended result, the AWT thread must be able to complete its processing first. The vagaries of thread management vary by platform, so be sure that your notion of thread timing is correct. In the example code, "Window Opened" should appear as the first line in the JTextArea to prove that the JFrame's thread is able to do its job ahead of the main thread. On Windows NT and Win98, simply reducing the main thread's priority allowed things to run in the order expected. The example adds Thread.sleep(1) to ensure that the AWT thread gets started. Most concurrency issues can be avoided by being prepared to delay in user response methods or by disabling relevant components until loading is complete, as seen in the example. The worst case is barely longer than under normal processing.
Let's take a look at the example code: In UseMainThread.java, the constructor sets up a JTextArea in the North area and a mock form composed of a JTextField, a JButton and a JComboBox in the South area. A volatile boolean is defined to hold state information for the JButton; the JComboBox is initially disabled. At this point, the JFrame is packed and shown, which starts up the AWT thread. Processing then continues in the main thread as follows:
// continue to other tasks after AWT thread start
Thread.currentThread().setPriority( Thread.MIN_PRIORITY );
sleeper(1);
load1();
load2();
The main thread's priority is lowered and a helper method, sleeper(), is invoked to pause the main thread, allowing the AWT thread to run first. As proof that this works, "Window Open" should be the first line in the JTextArea ( the windowOpened() method is used for this purpose ).
The load1() and load2() methods simulate long running tasks and append completion messages. In addition, load1() sets the boolean state variable; load2() enables the JComboBox. For the JButton "Press Me", actionPerformed() checks the boolean state variable, setting a waitcursor and looping with brief sleeps, if necessary. Figure 1 shows the JButton displaying this behavior, as well as the disabled JComboBox.
Figure 1: UseMainThread while Loading
Any actual work is performed after the state check indicates that loading is complete. Since the JComboBox is first disabled, then enabled on load completion; its wait handling is essentially automatic as seen in Figure 1 and Figure 2.
Figure 2: UseMainThread with Loading Complete
The delay timings are intentionally exaggerated to allow the effects to be seen in the example. With careful analysis, depending on the application and the initialization tasks to be performed, it is entirely possible for the application to show an apparent dramatic decrease in startup time, while the effects of the main thread tasking will not be noticeable to the user at all.
|