Maintaining UI Responsiveness

This is a bit of a rant on something that constantly annoys me about using my computer.  It's the lack of predictability regarding latency of simple operations.


Here's an example:  Click on the Start menu (assuming you're running Windows).  Did it appear instantly?  Or did your computer spend 5 seconds digging around on the hard disk before drawing it?  The answer is probably somewhere in between.  Click it again, and it will appear instantly.


Many things are like this.  An infamous one is the drives box in the standard Windows file dialog - clicking on that can easily take 10 seconds or so the first time, but after the first time, it's cached, so it's instant.


Funny thing is, some things really are (almost) always instant.  Pressing Alt-Tab for example.  It's very rare that you have to wait for the system to draw the fast task switch window.  Another thing that's fast is Ctl-Alt-Del, which takes you to the Windows Security screen.


Here's the thing:  It frustrates users when something doesn't work the same way every time.  Computers are the only appliances that do this - when you press the Start button on the microwave and it instantly comes on.  Press the Play button on a tape deck, and the tape starts playing.


Why?


Why are computers like this?  There are two reasons.  One is somewhat forgiveable:  Stuff gets swapped out.  If your computer has 256mb of memory, and you're doing stuff that takes closer to 400mb of memory, then a bunch of what you're working on is swapped out to disk, and when you try to switch back to it, it takes the computer a moment to get it all together.  (I have an idea that might help with this, mentioned below).


The more common reason, however, is that in order to make it seem that our programs are starting quickly, we defer as much of the work as we can for as long as possible.


Delay loading DLLs for example - plugins are a perfect example of this.  Some programs that support plugins defer populating the plugins menu until the user trips over the Plugins menu while looking for something, at which point the program has to do a lot of work loading up each DLL and interrogating it to see how to build the menu.  Frustrating.


And, for most users today, unnecessary.  I have a lot of RAM, I have CPU to spare.  There's no good reason that list of plugins shouldn't be ready for me when I want it.


What to do about it


There are ways around most of these problems.  I'm going to suggest two.


First, keep deferring long operations until after your program starts up  users do like it when the app is ready to use quickly - but then after the main UI is up and the user can start working, start a low priority task to prepare the things you've deferred.  Enumerate the fonts that are available.  Load the plugins.  Fill in the Favorites menu.

There are other things to keep in mind, of course.  If the system is low on memory, then caching isn't the way to go.  Be aware of the state of the OS around you - but if the system is idle and there's 400 meg of free memory, then why not initialize MSHTML in the background so that when the user wants to bring up a window that uses it, they don't have to wait a few seconds for it to load up.


This is what the little tool that Microsoft Office installs to run at Startup does - it loads up a big chunk of Office, so that when you do want to run any of the Office suite components, it's quick.  Some folks think it's cheating, but in the end it's what the user sees that matters.


Priorities


The other thing you can do is raise your UI thread's priority when appropriate.  Windows itself tries to do this (give elevated priority to the app the user is interacting with), but it doesn't seem to work very well.


Here's an example.  On my system, an Athlon XP 1700+, bringing up the Task Manager by pressing Ctrl-Alt-Esc happens almost instantly.  But if I start a CPU hog (as simple as main(){while(1);})  it takes my system over 3 seconds to bring up the Task Manager.


There's no excuse for this.  When I press Ctrl-Alt-Esc, the OS knows I've just requested something, and the user is waiting for that operation to complete.


Microsofot Outlook fails horrible at this test.  With my cpuhog.exe running, Microsoft Outlook 2003 takes over 5 seconds to switch between my Inbox and my Outbox.  Normally, it's instant, and with raised priority (using the Task Manager to set Outlook to AboveNormal) it's instant.


Outlook knows the user just clicked on something and is waiting for the response.  Getting a timely response to the user is more important than anything else the computer is doing at the time.  Anything that you're doing where you know the user is waiting for something (like painting a window or responding to a button click by bringing up a dialog) and expects it to be instant deserves a higher priority than the WinZip operation or video compression or game going on in the background.


You have to be careful about this since if you hog the CPU while you have an elevated priority level, you're going to severely hurt the rest of the system.. but careful application of elevated priority is a great way to improve the responsiveness of any application, especially on a busy system.


Locking things down


Something I want to experiment with is locking things down in memory.  Boot the system up, click on the Start menu, open IE, look through the favorites list and history and a few other things, and then lock every committed memory page so that it can't be swapped out.  This should guarantee that the Start menu can always appear instantly.  At least, I hope so.