Finding and Eradicating Big Footprint
April 28, 2003
Summary: Jon Fincher gives tips, tricks, and techniques for reducing footprint and speeding runtimes on Windows XP Embedded devices. (7 printed pages)
Welcome back to the ever-increasingly inappropriately named monthly column on Windows XP Embedded. Last month's column didn't make deadline, mainly because I was in Munich, Germany for Devcon Europe. Due to jet lag, time changes, and a hasty travel schedule, my body clock took four days to get back to normal once I returned. However, I wouldn't have missed that trip for the world—I love visiting Germany, and enjoyed the show immensely. All the sessions I gave or saw were full of customers, and all of them came for the reception for the free food and free access to the Microsoft crew. I met up with some old friends, made some new ones, and filled my camera's flash cards two or three times while I was there—and am looking forward to visiting there again next year.
Okay, that's enough of the travelogue. I wanted to delve into some more of the topics that have been covered on the Devcon tour since last year's kick-off in Las Vegas. This month, we'll be talking about footprint reduction, giving some hints, tips, tricks, and techniques along the way for keeping your runtimes as small (and fast) as possible. Let's get started.
First Step—Move to SP1
The first step if you're trying to reduce footprint is to upgrade to Microsoft® Windows® XP Embedded with Service Pack 1. As we were working on Windows XP Embedded with SP1, we fought component bloat at all times. While our number one focus is, and will be, on functionality, we also concentrated on keeping component sizes as small as possible. As a matter of fact, across the board we saw an average of 4.9 MB reduction in footprint sizes. A Minlogon configuration with Microsoft® Internet Explorer, Windows Media Player, and MSN® Messenger shows a 9 MB drop in runtime size when compared to the same configuration run with the original Windows XP Embedded tools and database. And we were fair about these numbers—we used a standard hardware profile for each scenario, with the same settings for each, which included putting the image on a compressed NTFS volume.
Second Step—Change Perspective
One of the trickiest and least successful ways to go about footprint reduction is, in fact, the most common method used by our customers. There are a few facets to this method:
- Adding anything and everything to a given configuration because you don't know what you might need, then trying to prune out the chaff.
- Including a shell in the configuration when, in fact, your device will be displaying your application as a custom shell.
- Starting with a full PMQ that was imported from a test machine, containing entries for every device it sees, whether or not it will exist on the final device.
- Including componentized (or installed on the device) applications with every option under the sun included, just to be safe.
That last one I like to call carving an elephant, after the joke, "How do you carve a statue of an elephant? Start with a block of wood, and carve away anything that doesn't look like an elephant."
Anyone who has followed this path knows that it leads directly to premature hair loss, a sudden rise in the stock price of Pepto Bismol due to the ulcer you're treating, and way too many unfinished wooden elephant statues. Trying to prune the image after a full dependency check is like trying to get the eggshells out of the batter after you've mixed it all together. You remove a component, and it's brought back in by the dependency check. You try turning off auto-resolve, and you get to answer a few hundred questions about which component you want—and you get to do that five to ten times in a row. You finally find a parent component to remove, and see the footprint doesn't go down as much as it went up because you've got orphaned components.
Building small runtimes is best approached from the opposite end: instead of carving an elephant, build one up out of clay.
Start Small, Build Up
The first big trick to making your runtimes smaller is to start with the smallest possible runtime you can make work on your device. This means the minimal amount of hardware needed to get a bootable system, and the minimal number of features to make sure your device is working properly.
To get the smallest possible hardware footprint, you'll have to prune your PMQ generated by TAP.EXE. I always recommend using TAP.EXE rather than TA.EXE, as you are almost always guaranteed to have a working configuration using a TAP.EXE-generated PMQ. A TA.EXE-generated PMQ usually doesn't produce a bootable system without major work. Once you have the PMQ generated (under a Windows 2000, Windows XP, or WinPE environment), open Component Designer and import it into a new hardware component. Set the prototype of your hardware component to the "Selector Prototype Component."
Now you can go about removing dependencies in the hardware component. In general, you can safely remove the following devices:
- Audio components and codecs.
- Video capture and display components.
- Floppy disks.
It Has Only One Button, and We Push It Before It Leaves the Factory
(Obscure Dilbert reference mandated by law—I had to include it.)
If you can't run TAP.EXE on your device, then you've got some work ahead of you. You need to identify all the hardware in the device that you will be using, and manually add the drivers for it all. While that may not be too tough for network adapters, video cards, maybe even chipsets, some devices are going to be difficult to track down. The worst thing you can run into is getting a blue screen trying to boot a runtime that you think is complete. So now what do you do?
Well, you can start with one of our predefined basic configurations, listed in the Component Browser under Software: Test & Development. These sample macros can boot 99 percent of all available hardware that will boot Windows XP, and are good generic starting points for device development.
You'd use these macros by adding them to a configuration, tweaking the settings as necessary, then building and booting. You should find that, on a majority of devices, the image will boot and you'll have something to start with. And best of all, the runtimes start small.
One thing you'll notice is that there are two similar sample macro components—one called Minlogon Sample Macro, and the other called WinLogon Sample Macro. The difference is simple (one has WinLogon, the other MinLogon), but also profound.
When we were first developing Windows XP Embedded, we noticed that winlogon.exe had a lot of static and delay-load dependencies, notably on a variety of security DLLs. Just getting the machine to log on as it should (even without an external network connection) consumed some serious footprint space. We decided to make some minor modification to winlogon.exe, and came up with minlogon.exe. It's static and delay load dependencies were greatly reduced, resulting in less footprint consumption, but there was a catch.
The catch with MinLogon is that we don't log on to the machine as a user anymore. Everything runs under the context of the Local System account, a predefined account built into Windows XP. Local System has access to everything—and I mean everything—in the system, so running applications or configuring the system is not a problem. However, since there are no user accounts (not even Administrator), anything user related is missing in a MinLogon system. Any behavior in your applications that relies on the current user context will probably not work as expected.
Configure, Configure, Configure
The first rule of real estate is location, location, location. The first rule of conserving storage real estate (that is, reducing footprint size) is configure, configure, configure. Okay, it's a stretch, but stay with me.
Most macro components that ship with Windows XP Embedded with SP1 have settings that allow you to configure them to include or remove specific components they depend upon. By inspecting the settings for these macros, you can usually find a dependency or two that you don't need.
There are a few components in the Component Database that lead to massive footprint bloat. They are:
- Explorer Shell
- Internet Explorer
- .Net Framework
As mentioned above, making your own shell component can help keep the Explorer shell out of your configuration and keep the runtime small. The .Net Framework is currently a monolithic component—that is, everything is in it, and there's no way to configure it so you only get parts of it. We're working on that, but for now, if you need .Net support, you're also going to get a big footprint.
Internet Explorer is probably the toughest thing to get rid of, simply because so many things depend on it, or parts of it. As an example, I was trying to analyze the dependencies needed to run standard Windows XP QFE install packages on a Windows XP Embedded runtime. I found that I needed to add about 120 MB of extra components to support the installation of 200 KB QFE. The culprit was a single function call into a single DLL that was part of the Help and Support Services component, which relies on Internet Explorer.
For reference, here are the components that will directly bring in Internet Explorer:
- .NET Framework [R1507].
- Help and Support Services [R1507].
- HTML Rendering Engine [R1507].
- IMAPI—CD Burning [R1507].
- Internet Connection Wizard [R1507].
- Internet Explorer (Additional Support) [R1507].
- Internet Explorer [R1507].
- Internet Explorer Group Policy Support [R1507].
- Internet Explorer Help Files [R620].
- Internet Explorer Technologies [R1507].
- Microsoft Vector Graphics Rendering (VML) [R1507].
- MSN Explorer [R1507].
- Outlook Express [R1507].
- Shell Namespace Extensions [R1507].
- Soap Client Runtime [R620].
- Windows .Net Messenger [R1507].
- Windows Media Player 8.0 [R1507].
- Windows Update Automatic Updates [R1507].
- Windows Update Base [R1507].
- Windows Update Shortcut [R1507].
Adding any of these components to your runtime will automatically bring in Internet Explorer, which is going to cause some serious bloat. If you can avoid these components, you should be Okay as far as keeping Internet Explorer from expanding your footprint.
Smaller Is Faster
One of the less obvious benefits to footprint reduction is the corresponding increase in performance from the device. However, it's not a truly obscure observation—a smaller footprint runtime will load fewer drivers, devices, and services, which will take up fewer resources, which means there will be more resources available for things like your application.
There are some caveats, though. A small footprint won't help much if you've got old, slow disk drives. Regardless of the size of the image or its media, the runtime isn't part of the equation until after BIOS and hardware checks are complete. And no matter how small the image is, it's still going to take some time to load your custom applications into memory. There's only so much that software can do for you.
Some ways to boost performance also help keep your runtime small. Use MinLogon rather than WinLogon, because MinLogon loads fewer system services, and has been shown to improve boot times by almost ten seconds. Load your application as a custom shell, because you only need to load one application rather than two. Keep the devices in your runtime to the minimum necessary, because loading and initializing drivers takes time and resources.
You Are Getting Sleepy… Sleepy…
Okay, you don't have to say it—my articles are good insomnia medicine. I know this, no need to remind me.
Now that we've had a nice nap, let's discuss a rather more obscure alternative to speeding boot times, namely, not booting at all—more to the point, booting only once, and using the ACPI Sleep mode (S3) to control the device.
The basic setup is something like this: put a master power button on the device that controls the power to the device. Put it in an obscure place, like on the back of the device, with a big red sign that says "Warning: Lark's Vomit." (Gratuitous Monty Python reference added for U.N. Resolution Compliance.) Then put a button on the front of the device that triggers the devices ACPI BIOS to send the device into Sleep mode. Document the switches for your users, and viola! You now have a machine that will shut down quickly (by entering sleep mode), and boot the second and subsequent times very quickly as well (by waking from sleep).
Obviously, this solution requires an ACPI BIOS in the device, and may require engineering a second power button, but very little else is needed. Since system security isn't involved in ACPI power states, this will work with a MinLogon runtime. ACPI itself has a minimal set of dependencies, so you won't be bloating your footprint with it. And if you're booting from flash, with its close-to-zero latency, you're not going to spend time waiting for the media to spin-up.
But, What If You're a Bear?
You could, if you need to completely disconnect your machine from external power, or conserve battery power, use the same setup but go to ACPI Hibernate (S4) instead of Sleep. This is a little trickier to manage, but still can be done. Hibernate requires system security be active and running, so you can't use MinLogon. Unless you want the user to log on every time they power up (should be fun on headless or keyboard-less devices), you'll have to add and configure auto logon features as well. You'll also need enough free space on the root of the boot drive to save the complete system state in hiberfil.sys. However, if you can meet this bar, you can have a shutdown that still starts up quickly and easily.
A Look Inside
One tool you can use to help you diagnose a slow booting system is BootVis, available from http://www.microsoft.com/hwdev/platform/performance/fastboot/BootVis.asp. BootVis logs everything that's done during a normal shutdown/startup cycle. The log can be used to help diagnose why a given system is booting slowly. While it's not a golden key into the realm of the XP boot loader, it is a tremendously helpful tool to have in your arsenal.
We've discussed some of the tools and techniques used for reducing footprint and speeding up your devices. Getting rid of shells (or replacing them with your own), substituting MinLogon for WinLogon where possible, and reducing device loads all help keep your devices small and fast. We briefly discussed a design change from booting/shutting down to using ACPI power states to control your device, and showed you BootVis for monitoring boot progress.
Next month—well, I'm not sure. Think of this as the end of a Bullwinkle cartoon that wraps up the storyline. You don't know what the next story line will be, but you know there will be another one, as fast as you can say Jack Robinson. Until then, post your questions/comments to the newsgroup—that's one of the places I'll be.