Writing Memory Efficient CE Applications
If the tutorials in this series had been ordered on the basis of their relative importance, this and the upcoming lessons dealing with memory use would have been first. Understanding how CE uses and manages memory in general is the key to your ultimate success on the CE platforms. This may seem like unnecessary detail, especially if your application doesn't do any memory allocation directly. However, even if you don't explicitly allocate memory, it is allocated in your behalf--by the loader--for your program's stack, heap, and static data storage. Thus, you still have to make informed choices to create a memory efficient application.
What does it mean to be memory efficient on a Win CE device? It means that your code, your data, and everything else in CE land should be able to gracefully coexist in 2 MB. No kidding. If this hasn't got your attention, take a moment and look at the file sizes of a few of your desktop Win 32 applications.
In the early days of Windows, we used to speak of the need for applications to be "well behaved". What we meant by this was that no application should acquire and hold so many resources that other applications couldn't execute when they got a time slice. In essence, understanding the rules and limitations of CE's memory environment is what makes your application "well behaved" in the CE world.
There are four areas we'll examine in this and future lessons on memory management:
- How CE memory is laid out
- How to choose memory allocation strategies for your application
- How to optimize the placement of application data
- What happens when the system is in a very low memory state
An understanding of these issues will allow you to make a smooth transition to the memory constrained environment of Windows CE.
Porting Tip: To be an effective CE programmer, you must understand CE memory architecture. The rules are not difficult to understand, but they are completely different than what you are used to on the desktop.
Something New Under The Sun
Before we begin to dissect the architecture of CE, let's step back and take in the panoramic view. Up to this point, we have framed the discussion in terms of porting Win32 code to Windows CE. This approach is informed by the bias that Windows CE is fundamentally nothing more than an "itty-bitty" Windows. While this has been a useful fiction up to this point, it is, in fact, not at all the case.
Windows CE is an entirely new computing model, a marriage between embedded systems technology and the larger Windows world. Its defining characteristic is mobility. The CE user doesn't "go to" a computer or a network; rather they carry these with them. In the CE world view, the network is wherever you are. Up to now, we've often heard the term "seamless" used to describe interoperable software applications. CE brings seamlessness to the human / computer interface.
As software developers, the importance of the "Windows-ness" of CE is twofold: First, CE abstracts handheld embedded computing with the stable, proven Win32 API, giving us a truly cross platform tool set for this genre of devices; And second, we have a large existing code base that is at least nominally portable to this API. Essentially, clothing personal embedded computing in the Win32 programming model provides developers with a huge productivity advantage. However, if we view this model too literally or too credulously, we lose sight of the real potentials of CE: inherent mobility and discretionary connectivity.
We need the Win32 abstraction for productivity reasons, but we also need to know how things really work "under the hood".