The original article is on
Rob Tiffany’s blog.
Does anyone else remember the good old days of DOS, when we spent time trying to squeeze more than 640Kb for drivers, programs, residents, and even Windows? Things like QEMM, HIMEM, EMM386.EXE give me fond memories.
')

Some of us even worked in OS / 2, which allocated 740Kb for our DOS sessions, providing them with preemptive multitasking. Yes, I could run several DOS games simultaneously in different windows without any problems. Surprisingly, I had a whole pack of crash-protected slots, each of which had its own 740K of memory.

Returning to today, you will see that Windows CE 5.0 and Windows Mobile 6.x have some similarities with their great-grandfathers from the 80s and 90s. The 32-bit embedded operating system, which we trust to manage our Windows phones, consists of a pack of slots, but unlike DOS with its 640Kb, your application receives 32MB of virtual memory. However, just like in DOS, you do not have access to the entire address space, because other things, such as system libraries, already use this space.
I recently met my good friend Glen Jones, who wanted to share some interesting findings with me. Keep in mind, it's not just that I consider Glen and his colleagues among the best Compact Framework developers in the world. His team designed and developed one of the largest and most complex applications running on Windows Mobile using the Compact Framework. Like any other companies that develop huge Windows Mobile applications, problems with lack of memory have not bypassed them.
Brian Pike, one of the architects of the "dream team", recently discovered that keeping an empty exe file in memory and storing forms, code, resources and data in separate managed assemblies reduces the amount of virtual memory consumed im slot, at the same time getting the opportunity to use the memory outside the slot within the 1GB of shared memory.To help clarify this incredible discovery, I’ll show two illustrations showing a memory map of a managed application running in two different ways. The application running on the emulators, which you see below, displays the use of 32 shared virtual memory slots. Red is the free memory, blue is used, green is reserved. Slot number 1 is full of system libraries and you can not help but notice that each subsequent slot has a small blue area. This space is used by the system and managed libraries, which means it’s impossible to get your honest 32 megabytes.
On the left, you see the Compact Framework StandardExe.exe application running in slot 14. This simple managed application contains 2.25 MB of bitmap as a resource and the form on which this bitmap is located. If you look closely, you can see that 2.25 blue megabytes is in the bottom of slot 14. This space is occupied by our exe-file.


On the right is OptimizedExe.exe running in slot number 11. This is a completely empty exe-file. The Main function calls the static class method in the managed DLL and that's it. As a result, we get an exe file of 5 kilobytes. In a managed build called OptimizedDLL.dll we have the same 2.25 megabyte bitmap and form.
If you look at the image on the right, you may be surprised to find that there are no blue areas in slot 11! And if you look more closely, then the 2.25 megabyte assembly can not be found anywhere else.This is great enough and greatly increases our capabilities. Potentially it becomes possible to develop many games and applications that have not previously been seen on Windows phones.
Attention, the question. How is this possible? It `s Magic?Those of you who have read Steven Pratschner's
blog know that the Compact Framework places managed exe and dll in the first gigabyte of shared memory outside the slot in which your application runs, which is certainly great.
But what you might not know is that the operating system automatically locks at the bottom of the slot just as much memory as your exe file occupies. Thus, despite the fact that the CLR controls the execution of the application and locates it in shared memory in a passion of love, Windows CE selects a precious portion of memory, because it is completely sure that our application works there.
But our application is managed and it is not there! Those of you who have huge managed exe-files, you lose a huge chunk of memory in your slot, which could be used with much greater benefit! So the first lesson is to do what Brian did — create an empty exe file in the form of a stub that runs the application from a separate managed assembly.
Your empty exe file might look like this:
using System;
namespace OptimizedExe
{
static class Program
{
///
/// The main entry point for the application.
///
[MTAThread]
static void Main()
{
OptimizedDLL.StartUp.Main();
}
}
}
* This source code was highlighted with Source Code Highlighter .
Library with the application:
using System;
using System.Windows.Forms;
namespace OptimizedDLL
{
public class StartUp
{
public static void Main()
{
Application.Run( new Main());
}
}
}
* This source code was highlighted with Source Code Highlighter .
So, we have learned to beat Windows CE, playing by its own rules. Now it's time to talk about a curious situation with our managed build. If you read Reed Robinson’s
blog about killing a monster in memory, you probably know that libraries are eating up memory in the slots from above, taking up more and more, which doesn’t sound very fair. We call this "dll crunch" (rattle of libraries), because free memory remains between the libraries and the exe file. But I have good news. Guided assemblies do not behave this way! In fact, they not only do not occupy any of the slots, they don’t touch your main slot. How is this possible?
Managed builds are not full dll! The CLR treats them like regular files and loads them into gigabytes of shared memory. For Compact Framework, managed assemblies are simply files full of IL commands that do not fall into the process slot. Now you understand where is 2.25 bitmap that we placed in OptimizedDLL.dll. It is abroad the 32 megabyte barrier of your slot, and thus it does not waste precious memory!
So, if I follow this new way, will I ever have virtual memory, or did I get a free lunch?Lunch is definitely not free, but at a discount. The JIT compiler runs in your slot and loads the IL code needed for the current call stack. Resources that do not need to be compiled or executed will never be loaded there. The heap of the garbage collector (GC Heap) is also in your slot, and it is there that the objects you select hang. Your slot contains a 64KB Thread Stack that your process spawns. There is also a bunch of application domain (AppDomain Heap), which contains views of the structures described in your assemblies.

So, summarizing the above.
1. You can minimize the erroneous allocation of unused operating system memory by following the pattern described above with the location of the entire application inside managed assemblies, which will be called from an empty stub application. We will lose some 5Kb. Thanks, Brian!
2. By placing managed assemblies in shared memory, you will reduce the harm to other applications on your phone, caused by "library rattle." This will also reduce the memory consumption in the slot of your process.