This behavior you are seeing is normal by design.
The /3gb switch and LARGEADDRESSAWARE link flag cause the OS to allow a
process to use 3gb of addressable user space.
(history for any other readers of this thread)
Each "normal" process has 4gb of address space (consider a 32-bit pointer).
There are extentions that allow you slide a window through more memory,
but fundamenatlly you cannot escape the fact that common x86 machines only
support 32-bit addresses (therefore 4gb). Normally the OS uses the top
half of memory (virtual address space) for system space. (i.e. thats where
the the "kernel" lives). If you pass /3GB in the boot.ini as a flag to the
kernel, it will an extra check during the loading of a process. This extra
check will look for the LARGEADDRESSAWARE flag (settable by linker option
or with imagecfg). If that flag is set, the OS will erect a process with
3gb user space, and 1gb system space. However, through that 3gb of system
space, there are already quite a few little modules sprinkled about.
If you review the allocations that already exist on process creation,
you'll see that there is quite a bit thats already allocated. (again this
is va space thats allocated.) A simple "lm" after loading a small native
app in ntsd (say "ntsd calc.exe") shows:
0:000> lm
start end module name
01000000 0101f000 calc (deferred)
77290000 772d9000 SHLWAPI (deferred)
77380000 77b5d000 SHELL32 (deferred)
77ba0000 77bf4000 msvcrt (deferred)
77c00000 77c44000 GDI32 (deferred)
77c50000 77cf4000 RPCRT4 (deferred)
77d00000 77d8f000 USER32 (deferred)
77da0000 77e30000 ADVAPI32 (deferred)
77e40000 77f34000 kernel32 (deferred)
77f40000 77ffa000 ntdll (pdb symbols)
(yes.. thats a 2gb machine... i dont have my 3gb machine handy right now)
Meaning that the largest linear region of memory inside 2gb we could
allocate at this point would be 0x76271000 or 1.9 gigs.
When you have a more complicated app in memory, (say something running
managed code) you have many more dll's loaded at various places in memory.
That said, the gc is only able to allocate from the pool of free memory,
and have a few hundred megs of virtual address space consumed when an app
is running is not uncommong. (thats va space. so, it just means that its
atleast reserved, and maybe not actually allocated). On some Oses (depends
on what all is being loaded into a process) your ability to allocate
certain amounts of memory will vary. So, for instance running inside a
debugger will lower the amount you'll be able to allocate.
I'd expect that in general you'll have better luck trying to allocate
smaller chunks. But, dont expect to be able to get the full 3gb (with /3gb
enabled) or the full 2gb with normal 2gb enabled.
-scott
--------------------
From: "Alec Seward" <
[email protected]>
Subject: Re: .NET Framework Can't use Available Memory
Date: Thu, 17 Jul 2003 10:57:01 +0200
Jim,
I have managed to squeeze out 2.4 Gb to one process in NET v1.1, on a 4Gb
computer running WinXP Pro.
1. Add the /3GB switch in boot.ini (as you did)
2. After building you program run the linker (located in e.g. C:\Program
Files\Microsoft Visual Studio .NET 2003\Vc7\bin)
link -edit -LARGEADDRESSAWARE target.exe
where "target.exe" is your application executable
Now run the executable and you should be able to allocate up to 2.4Gb to
the
process.
Why it stops there and don't reach 3Gb, I don't know.
An unmanaged process can of course access all of the available 3Gb of user
memory in Windows).
Does anyone know if it is possible to do this in .NET/CLR as well?
Best
Alec Seward
"Memory limitations, memory limitations...why are there so many of them?"
----- Original Message -----
From: "Jim Snape" <
[email protected]>
Newsgroups: microsoft.public.dotnet.framework
Sent: July 15, 2003 14:31
Subject: .NET Framework Can't use Available Memory
I need to cache large amounts of data for fast lookup, hence I've been
running some tests on various operating systems (XP, Win2k Adv etc) and
it
seems that no matter how much physical memory is available a .NET
framework
application can not use more that 1.2GB. I have even tried with a 4GB
machine using the 3GB boot time switch.
Is there some hard limit built into the framework? I can't believe it
would
be handicapped in this manor. Is there any way of circumventing the
limit?
Thanks in advance,
Jim
p.s. For reference, the code I used to test the limit is:
using System;
namespace MemAlloc
{
class MemBlock
{
private MemBlock next;
private byte[] data = new byte[1024*64];
const int OneMeg = 1024 * 1024;
static void Main(string[] args)
{
try
{
MemBlock first = new MemBlock();
while (true)
{
MemBlock next = new MemBlock();
next.next = first;
first = next;
Console.WriteLine("MEM: {0} MB",
GC.GetTotalMemory(false)/OneMeg);
}
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", ex.Source, ex.Message);
}
}
}
}
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
Note: For the benefit of the community-at-large, all responses to this
message are best directed to the newsgroup/thread from which they
originated.