MemMaker for the .NET Compact Framework

Does everyone remember the good old days of DOS when we used to spend our time making more of the 640 KB memory space available for our drivers, programs, TSRs and even Windows?  Things like QEMM, HIMEM.SYS and EMM386.EXE bring back fond memories for me.  We had this one slot and Billg said we’d never need more than 640 KB.

DOSMem

Some of us even switched to OS/2 which could give us 740 KB to our DOS sessions while providing them with preemptive multitasking.  Yes, I could run multiple DOS games in multiple windows simultaneously with no degradation.  Wow, now I had a bunch of crash-protected slots each with 740 KB of memory.

dos

 

If you fast forward to today, you’ll see that Windows CE 5.0 and Windows Mobile 6.x shares some commonalities with their forefathers from the 80’s and 90’s.  The 32-bit embedded operating system that we rely on to power our Windows phones is made up of a bunch of slots.  The mobile applications that you build run inside one of these slots and unlike DOS with its 640 KB memory space, your app gets 32 MB of virtual memory space.  But just like with DOS, you don’t get access to the whole space because other things like system DLLs are already eating into your free virtual memory. 

Many of you might not care because you build simple apps that use very little memory.  On the other hand, most of the people and organizations I work with build the largest, most memory-intensive applications ever seen on the mobile device.  Needless to say, these folks aren’t too pleased that they don’t get the whole 32 MB of virtual memory that’s coming to them.  They probably wish they a utility like QEMM or MemMaker to put things in high memory.

I recently met with a good friend of mine who wanted to share some interesting findings with me.  Keep in mind, not only do I consider this person and his colleagues to be some of the top Compact Framework developers in the world, his team members designed and developed of one of the world’s largest, most complex managed apps running on a Windows Mobile device.  Like many organizations that have built very large Windows Mobile applications, free virtual memory issues and the "DLL Crunch" have deprived this app from of all the memory it would like to have.  One of the architects on this "Dream Team" noticed that by keeping their application’s EXE empty and putting all the forms, code, resources, and data in managed DLLs, he reduced the amount of virtual memory his app uses inside its slot while at the same time taking advantage of memory outside the slot in the 1 GB shared memory area.

To help you visualize this, I’m going to show you 2 pictures of the Windows Mobile process slots running a Compact Framework application two different ways.  The virtual memory viewer you see running in the emulators below shows the 32 slots in the User space of the OS.  Everything in Red is free virtual memory, Blue is committed memory and Green is reserved.  Slot 1 is crammed full of ROM DLLs and you can’t help but notice the area of Blue at the top of every other slot.  That’s space out of everyone’s slot being used by system and other native DLLs which means nobody’s going to get their fair share of their 32 MB slot space.

On the left you’ll see a NETCF app called StandardExe.exe running in slot 14 of the operating system.  This simple managed EXE has a 2.25 MB bitmap bound to it as a resource and a single form that compiles to the same size as the bitmap inside it.  If you look at the picture on the left, you’ll see a 2.25 MB Blue area coming up from the bottom of slot 14.  This represents the space being taken up by the EXE.

StandardSM      OptimizedSM

On the right a NETCF app called OptimizedExe.exe running in slot 11 of the operating system.  This managed EXE is completely empty.  The Main function calls into a static class of a managed DLL and that’s it.  No mas.  This results in an EXE with a file size of 5 KB.  In the managed DLL we have the same 2.25 MB bitmap bound to it as well as a simple form.  This compiles into a 2.25 MB DLL called OptimizedDLL.dll.  When you look at the picture on the right, you’ll be hard-pressed to see any Blue area coming up from the bottom of slot 11.  A closer look reveals the 2.25 MB DLL is nowhere to be found either.

This is pretty cool and has the potential to unleash the largest, most powerful games and applications Windows phones have ever seen.  So the big question is, how is this happening?  Is it magic? 

Those of you who have read Steven Pratschner’s blog know that the Compact Framework memory maps your managed EXE and DLLs into the 1 GB shared memory area outside the slot your app is running which is cool.  What you may not know is that the OS automatically blocks out virtual memory at the bottom of your slot that’s the same size as your EXE.  So even though the CLR is in control of app execution and is giving you lots of love by putting your managed EXE up in the shared memory area, Windows CE takes away a valuable chunk of memory because it thinks that’s where your EXE is running.  Guess what, your app isn’t running there and it’s not native.  For those of you with giant managed EXEs, you’re losing out on a lot of virtual memory in your slot that could be put to good use.  So the first lesson here is to do what Brian did and make your EXE nothing but an empty stub used to launch your app which really lives inside managed DLLs.

Your empty EXE code should look like the following:

using System;

namespace OptimizedExe
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
        static void Main()
        {
            OptimizedDLL.StartUp.Main();
        }
    }
}

Your DLL code should look like the following:

using System;
using System.Windows.Forms;

namespace OptimizedDLL
{
    public class StartUp
    {
        public static void Main()
        {
            Application.Run(new Main());
        }
    }
}

So now that you’ve learned how to instantly give your managed apps more memory by beating Windows CE at its own game, let’s talk about the curious case of your managed DLL.  If you’ve read Reed Robison’s blog discussion about Slaying the Virtual Memory Monster, you know that DLLs seem to take up everyone’s virtual memory from the top of the slot down which doesn’t sound too fair.  DLLs keep pushing their way down everyone’s slot causing something we call the “DLL Crunch” as free virtual memory get’s squeezed between the DLLs and EXEs.  I’ve got some good news for you.  Managed DLLs do not exhibit this same behavior.  In fact, not only do they not use up memory in all the other slots of your Windows phone, they don’t even push downward on the memory of your own slot.  How could this be?

Managed DLLs are not DLLs.  The CLR just treats them as files that it memory maps into the 1 GB shared memory area.  To the Compact Framework, managed EXE and DLL assemblies are just files full of IL that it maps outside your process slot.  So now you know where the 2.25 MB bitmap that we bound to OptimizedDLL.dll is.  It’s beyond the 32 MB barrier of your slot and therefore not using up your valuable memory. 

So if I follow this new pattern for NETCF development, will my slot ever have virtual memory allocated or do I get a free lunch?

While there’s no free lunch, you did get a buy one get one free discount.  The JIT compiler is running in your slot and it pulls in IL from the 1 GB space as needed to compile the current call stack.  Resources that aren’t designed to be compiled or executed will never be pulled down here.  The GC Heap is in your slot and that’s where your currently allocated Objects and instance variables are hanging out.  Your slot maintains a 64 KB Stack for every Thread your app spawns and the AppDomain Heap maintains a representation of the data structures found in your assembly’s IL.

image

So what are the big takeaways here?

You can eliminate the erroneous and wasted allocation of EXE virtual memory in your slot by following the pattern of using an empty stub managed EXE to kick off your application.  Windows CE will now only block out 5 KB of memory.

You can take better advantage of the 1 GB shared memory area by putting your entire application inside managed DLLs.  This will make your app a good neighbor by not creating the dreaded “DLL Crunch” for all the other apps on your Windows phone.  It also reduces the amount of memory that has to be allocated inside your slot.

This new pattern of managed development on the Windows Mobile platform is a true breakthrough in memory management.  Come join me at Tech Ed 2009 this May in Los Angeles for a complete deep dive on this new way of building memory-intensive games and applications.

- Rob

Published 09 April 09 06:12 by robtiffany

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# MemMaker for the .NET Compact Framework | Microsoft Share Point said on April 9, 2009 10:11 PM:

PingBack from http://microsoft-sharepoint.simplynetdev.com/memmaker-for-the-net-compact-framework/

# Alberto Silva said on April 10, 2009 2:29 PM:

Um título destes seria digno de abertura de um qualquer telejornal nacional! Recebi hoje pelo Newsgator

# Auri Rahimzadeh said on April 10, 2009 3:02 PM:

Great article!

Where do we get that Virtual Memory mapper utility? That looks awesome.

# Alex Yakhnin's Blog said on April 10, 2009 3:58 PM:

Check out the Rob's blog post in which describes the technique that can help you to allocate less memory

# Auri Rahimzadeh said on April 10, 2009 4:00 PM:

Great article!

Where do we get that Virtual Memory mapper utility? That looks awesome.

# Alberto Silva - Device App Development MVP said on April 11, 2009 3:49 AM:

Auri,

The utility Rob has used can be obtained from a CodeProject article:

http://www.codeproject.com/KB/mobile/VirtualMemory.aspx

# Paul Yao said on April 11, 2009 9:18 AM:

Rob --

Cool tip!

I wonder if there is time for me to get a link to your blog into my book. Hmm.

Best,

Paul

# Raffaele Limosani said on April 15, 2009 12:27 AM:

I always knew that managed DLLs are handled by the OS as files and therefore loaded into the LMA (Large Memory Area) instead of wasting my process slot’s virtual memory (see my very first post ever :-), but I’ve never tested this incredibly simple idea…

Thanks Rob for spreading it out!

~raffaele

# Jed said on April 16, 2009 1:38 PM:

This winds up being a nice side effect of creating reusable code - see the old Mobile CAB stuff, for example.

Most companies building more than one app should tend towards this type of design anyway.

# Morten Damsgaard said on April 23, 2009 4:03 AM:

Hi Rob,

Great article. I think your "empty" managed exe will take 64kb (and not 5kb) of virtual memory, because CE maps dll's and exe's into 64kb boundaries.

- Morten

# dvescovi said on April 23, 2009 5:28 PM:

Does all this hold true only for Windows Mobile up to 6/6.5 which uses the Windows CE 5.0 Kernel? I am wondering what your take on this or even if its even applicable under CE 6, which has a major memory archicture shift. My guess is Windows Mobile will adapt the CE 6 kernel sooner or later as I assume the reasion for the rearchicture probably came from the WM team as they are the biggest customer.

David Vescovi

# robtiffany said on April 23, 2009 8:30 PM:

You're correct David.  This pattern is only needed for versions of Windows Mobile that run on top of Window CE 5.0.  Those versions include 5.0, 6, 6.1 and 6.5.  Windows CE 6.0 has a redesigned kernel that supports 32,000 processes and each process gets 2 GB of RAM.

-Rob

# robtiffany said on April 23, 2009 8:33 PM:

Morten, as of Windows Mobile 6, the CE 5.0 kernel was altered so that Module (Executable) DLLs could align to 4K boundaries which saved a lot of memory.  File (Read-only) DLLs remained aligned to 64K boundaries though.

-Rob  

# monxalo said on May 11, 2009 10:22 AM:

Greetings,

Does this behavior applies to dynamic loaded assemblies?

Using Assembly.Load ?

- Gonçalo

# Dave Glover "Down Under (Oz)" said on May 12, 2009 9:36 PM:

I twittered this awhile back, but appreciating not everyone twitters I wanted to share this on my blog

# The Windows Mobile RSS (Reed and Steve Stuff) Feed said on May 13, 2009 10:48 AM:

There is a lot of good stuff going on a Tech-Ed this week in LA. &#160; In you are here, come by and

# Andrew Konovalov said on May 30, 2009 5:48 AM:

Hi, Rob!

I've recently translated your article into Russian and here is one interesting comment from an experienced guy:

==

>> But just like with DOS, you don’t get access to the whole space

>> because other things like system DLLs are already eating

>> into your free virtual memory.

Using the following function calls

SetKMode(1); SetProcPermissions(0xffffffff);

allows a developer to write anywhere (getting access to the whole space). It's better not to use other 32Mb because there is XIP, so it can lead to hard reset.

Translating address space of other processes can be achieved either using MapPtrToProcess() or appending dwVMBase value from Process structure (which can be fetched from aInfo[KINX_PROCARRAY] array of KData structure). The address is static and depends on architecture, but for ARM is always the same.

Enjoy!

==

# Andrew Konovalov said on May 30, 2009 5:51 AM:

Here is also a good illustration of full address space mapping: http://i.msdn.microsoft.com/Aa450572.mm2(en-us,MSDN.10).gif

# Andrew Konovalov said on May 30, 2009 11:53 AM:

Short amendment regarding not using "other 32Mb". It really meant to be the particular memory range  0x2000000-0x4000000 (the XIP location).

# Русский блог Windows Mobile said on June 1, 2009 2:14 AM:

MemMaker для .NET Compact Framework Оригинал: http://blogs.msdn.com/robtiffany/archive/2009/04/09/memmaker-for-the-net-compact-framework.aspx

# The Windows Mobile RSS (Reed and Steve Stuff) Feed said on June 10, 2009 5:13 PM:

Now that the Windows Mobile 6.5 DTK is available, you are probably starting to discover some of the new

# simon.tamman said on July 15, 2009 1:53 PM:

Brilliant, and it just so happens that due to my rather pedantic architecture hat I have already done this (without even realising the virtual memory saving feature it provides). Our .exe just creates an instance of "App" and runs. :)

Nice to know this though. It may help some other projects here!

Reggies

Jax

# robtiffany said on July 16, 2009 9:01 PM:

I'm just glad to see folks from our mobile community are observant and curious and therefore point out bugs in our system.  It's also nice to see people put forth workarounds to help everyone else.  Raffaele Limosani in Italy was on to this issue over a year ago when he made it public on his blog.  He knew that managed exe's whould take up slot space equal to their file size and that managed dll's wouldn't, which leads to the workaround of putting all your code in dll's.  The only reason we're even talking about this issue is because Windows Mobile 6.x still uses our older version of Windows CE 5.0 and not our current version where this has been fixed.  Thanks to Brian,  Raffaele and all those inside Microsoft who have made subtle memory issues clearer to our developers.

# Faiyaz said on July 22, 2009 1:20 AM:

Great finding sir.  Thanks for sharing the info.  Hope some of my issues will now be resolved.

# Sean Solt said on November 17, 2009 4:35 AM:

Hi Rob!

I need a little support. I have a really huge .NET cf application. I fight with the memory limit for a while. I tried your method and used the memory mapper program to watch the changes but there were nothing changed. I put my program completly to a DLL as you advised and call it from an "empty" exe but the memory map remained the same as before the change. What can be the problem? (using WM5).

Thank: Sean

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

Search

This Blog

Syndication

Page view tracker