As I’ve mentioned, applets can be a plague on your system. The annoying thing is that it’s possible to write applets that aren’t so horrible. And most of the mitigations are really just common sense ideas – there’s nothing spectacularly complicated in any of them.
As with the earlier posts in this series, some of the mitigations are common to all types of applets (and all applications in general), and others are specific to various types of applet.
Let’s start with the basics…
For applets that run all the time:
Do you REALLY need to have an applet running all the time? The best applet is one that doesn’t run at all. Is it possible to bundle your applet’s functionality into an application that the user invokes? The start menu highlights newly installed applications, so your new application will be visible there, worst case there are other mechanisms for installing your application in locations that are visible to the user (the desktop is one of them (although that has its own set of issues)).
Now that you’ve decided you need an applet that runs all the time, please reconsider. Seriously. I know I just asked you to think about it, but really. Steve Ballmer says that sometime in 2008, a billion people will be running some version of Windows, that’s a LOT of people. If your product is successful, you’re likely to be selling to a couple of million of them – do you believe that your applet provides enough value to every one of those customers that you need to have it running in their face? Really?
Once you’ve decided that you REALLY need to have an applet running, make sure that there’s a way for the user to turn it off. There’s nothing more annoying than realizing that the software that came with some random piece of hardware that I use maybe once or twice a month is running all the time on my machine.
If you’ve written an applet because you want to let the user know about some cool feature, why not use the RunOnce key to let the user know about the feature, letting them know how to discover the feature later on, then shut up and never bother them again?
For all applets (and all applications that are expected to run all the time):
Think about how to reduce the applets impact on the user. Reduce the DLL load in your applet whenever possible – each DLL you load consumes a minimum of 4 private pages (16K on x86) and takes between 500K and 1M cycles to load. Anything you can do to reduce that is better. If you can get away with just loading kernel32.dll and the C runtime library, it’s better. Consider delay loading DLLs that you infrequently use.
Reduce the stack size used for the threads in your applet – by default Windows threads get a 1M commitment and 10K of reserve (which really turns into 12K of reserve due to paging). That means that every thread is guaranteed to consume at least it’s stack commitment space in virtual memory (the good news is that it’s virtual memory – normally that’ll just be space reserved in the paging file, not real memory).
Reduce the number of processes that your applet needs. There’s rarely a good reason for you to require more than one process to do work. About the only one I can think of is if you split functionality to increase the amount of code you have running at a high privilege level). As an example of this, in Windows Vista, the audio stack runs in two separate services – the AudioSrv service and the AudioEndpointBuilder service. This is because a very small part of the functionality in the audio engine has to do some operations that require LocalSystem access, but the rest of the audio stack can run just fine as LocalService. So the AudioEndpointBuilder service contains the high privilege code and the AudioSrv service contains the rest. If you feel you need to have a separate process to provide reliability (you run the code out-of-proc in case it crashes), windows Vista provides a cool new feature called the “restart manager“. The restart manager allows the OS to restart your application if it crashes, reducing the need to run code out-of-proc.
Don’t forget that Windows is a multi-user system. Some of your customers won’t want your applet, others will. So make sure that the settings to enable/disable the applet are instanced on a per-user basis. It’s really annoying when you right click on a notification area icon and see that the “disable this” menu is disabled because you’re running as a normal user (which is most users on Vista). Whenever I see this, I know that the author of the applet didn’t consider the normal user case.
If you can target Vista only, consider reducing your thread and I/O priority. If your applet is performing processing that’s not directly related to the user, use the new PROCESS_MODE_BACKGROUND_BEGIN option in the SetPriorityClass API to let the system know that your process should be treated as a low priority background process – that way your applet won’t preempt the user’s work. You can also use the new FileIoPriorityHintInfo method of the SetFileInformationByHandle to let the OS to prioritize your I/Os to a handle below that of other user operations.
Next: Mitigations for updaters (no post tomorrow since I’m moving offices).