.NET Process Maximum Memory

This whole article started because of the a memory leak in my Fares Engine…

The maximum allocatable size of a .NET process depends on the following factors: CPU, OS, 32/64 EXE header, GC

OutOfMemoryException

The maximum allocatable size of a .NET process depends on the following factors:

  • The CPU, which for the .NET universe is
    • x86 which has a 4GB address range, although in practice the actual available memory is around 3.2GB as the BIOS and video share the available address range.
    • x64 which has an address range of 18.45 exabytes which is practically unlimited (although we said that about 386, x86 and y2k)
    • Italium , which is beyond the scope of this article.
  • The Windows operating system
    • Windows 98/ME
    • Windows NT/XP/2000 (x86 and x64)
    • Vista (x86 and x64)
    • Windows Server 2003 (x86 and x64)
  • The headers PE signature of the OS Process /LARGEADDRESSAWARE
  • Available swap space

The x64 platform (x64 CPU, x64 OS) will yield a maximum process size in excess of the available system RAM. For example, my 8GB Windows 7 machine was able to yield a process of 8,656 MB, although
at that point the system was swapping so much it was unusable.

The x86 platform (x86/x64 CPU, x86 OS) will yield 1.5GB as the maximum process size be DEFAULT.
Most people assume this will be 2GB, however the garbage collector needs its own space and does
not allocate the maximum.

It is possible to allocated over 2GB on a .NET x86 process by marking the assembly or EXE
with /LARGEADDRESSAWARE. This cannot be done via Visual Studio, although you can
create a Post Build Event (see attached solution for an example). Execute the following
command-line tool EDITBIN.EXE /LARGEADDRESSAWARE MyApp.exe. This command can normally
be found in C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin. In order to confirm
that the binary headers have been correctly updated run the following command DUMPBIN.EXE /HEADERS MyApp.exe, which should give:

Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file MaxMemory-x86-LargeAddressAware.exe
PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
14C machine (x86)
3 number of sections
49FDF23D time date stamp Sun May 03 20:36:29 2009
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
122 characteristics
Executable
Application can handle large (>2GB) addresses
32 bit word machine

Strangely, it easier to test this on an x64 system which has lots of available memory. In tests (see test utility described later) I have been able to allocate 2’803MB.

It is more complex on a x86 systems as the operating system must have the /3GB switch in the c:\boot.ini file. For example, marking an .NET application with /LARGEADDRESSAWARE, but running it on a Windows XP system will yield 1,500MB max — even if the machine has the maximum physical RAM of 4GB/3.2GB free! You need to have both /LARGEADDRESSAWARE on the specific application, and the operating system configured with /3GB.

.NET Maximum Memory Test Tool for x86, x64
I have found it tricky to isolate the different factors and to marry up the theory with actual hands-on results. To this end I created a utility allocate increasing amounts of memory (in 64KB chunks) to determine the actual maximum allocatable memory for a particular system (CPU, OS, RAM, swap space, and configuration /3GB, /PAE)

The utility comes in three flavours:

  • x64 — called "MaxMemory-x64.exe"
  • x86 — called "MaxMemory.exe"
  • x86 + /LARGEADDRESSAWARE — called "MaxMemory-x86-LargeAddressAware.exe"

Table of Findings

  • I am able to allocate 8,656MB using "MaxMemory-x64.exe" on x86, Windows 7, 8GM RAM
  • I am able to allocate 2,803MB using "MaxMemory-x86-LargeAddressAware.exe" on x86, Windows 7, 8GM RAM
  • I am able to allocate 1,411MB using "MaxMemory.exe" on x86, Windows 7, 8GM RAM
  • I am able to allocate 2,191MB using "MaxMemory-x86-LargeAddressAware.exe" on x86, Windows XP + /3GB, 2’496MB RAM, VMWare
  • I am able to allocate 2,178MB using "MaxMemory-x86-LargeAddressAware.exe" on Xeon, Windows Server 2003 SE + /3GB, 2GB RAM, VMWare
  • I am sure the tweaking the allocations and system configuration by yield better results, and that the actual number may also vary from attempt to attempt.

On the x86 platform, allocations above the 1,500MB mark seem to be very slow. I do not know why this is the case.