The Windows boot.ini
file has a /MAXMEM
switch whose name would lead you to believe that it sets the maximum amount of memory that Windows will use. But that's not what it does; the name is misleading.
What the /MAXMEM
flag really does is set the maximum physical address that Windows will scan in search of RAM. If your physical memory map contains discontiguous chunks of RAM, such as the one at the 3.5GB boundary in the sample diagram I drew a few months ago, then the amount of RAM Windows finds will be less than the /MAXMEM
value you specified. For example, if there were a gap between 128MB and 256MB (said gap used by some hardware device, say), then setting /MAXMEM to 512MB would only give you 384MB of RAM. You lost 128MB of physical address space to the gap.
What's more, Knowledge Base article Q108393 says
Microsoft has not committed to keeping the switch in any future releases of Windows.
In fact, Windows Vista carries through that threat. The /MAXMEM
switch has no effect in Windows Vista. To try to avoid the confusion surrounding the meaning of MAXMEM
, the kernel folks changed its name to TRUNCATEMEMORY
. (It also specifies the physical address limit in bytes rather than megabytes.) I'm not sure the name change will really help much to dispel the confusion, though, since it still says "memory". I think they should've called it something like MAXPHYSADDR
.
Does Windows always "scan for RAM", or are there cases where it trusts the e820 map provided by the BIOS? Come to think of it, is that e820 map what you’re talking about when you refer to scanning?
(When I heard the term "scan for RAM", I had pictured the kernel going through some kind of loop, trying to do something with each physical address up to some limit, to figure out if there was RAM there. Perhaps that isn’t at all what happens, though?)
Actually, this seems to be a very low level kernel question, so I have a feeling you may not even know. Still, if you do, the information may be helpful — I’m not sure for what, but oh well. ;-)
I actually had to use the /MAXMEM switch. We had an Exchange Server that was running NT 4.0; then we updgraded it to Windows 2000; then (much later) we added RAM to take it from 2GB to 4GB.
Two days later it froze.
After all kinds of troubleshooting we figured out that whenever the Exchange Store process hit 2GB, it froze.
We used the /MAXMEM switch to limit the server to an amount of RAM that would stop the freezing.
Then I had a flash of insight and upgraded the network card drivers. It never froze again.
TRUNCATEMEMORY is better, to my opinion, cause it accents the fact of truncation, instead of assuming that the user knows much about physical memory mapping, like MAXPHYSADDR does.
Maurits: it’s still recommended to use /MAXMEM on Exchange servers if you fit more than 4GB. The reasons are complex – you’re recommended to use the /3GB and /USERVA switches to allow the store process to use (nearly) 3GB of virtual address space, but this reduces the kernel address space to (a little over) 1GB. If you fit more than 4GB of memory, to address it all you need to go into Physical Address Extensions mode (/PAE switch). This doubles the size of the page tables. Also, the page frame database is bigger due to having more physical memory pages to describe.
The net result of all this is that there’s not enough kernel address space left to support a lot of connections, so overall your Exchange server’s performance is worse with 8GB than with 4GB. Either use /MAXMEM or remove 4GB of memory!
It might be worth noting that if your goal is to actually reduce the amount of physical memory available to Windows by a set amount, the /BURNMEMORY switch is your friend.
If Microsoft *really* cared about compatibility and consistency they would use MaxPhysPage. :)
http://support.microsoft.com/kb/83436
"If Microsoft *really* cared about compatibility and consistency they would use MaxPhysPage."
And continue support for MaxBPs.
TRUNCATEMEMORY?
Are they sure there wasn’t any longer word?
Again, contradictory info from M$ as usual:
http://www.microsoft.com/technet/sysinternals/information/bootini.mspx
/MAXMEM=
Limits Windows to ignore (not use) physical memory beyond the amount indicated. The number is interpreted in megabytes. Example: /MAXMEM=32 would limit the system to using the first 32 MB of physical memory even if more were present.
A Hofstadter fan slipped this into the documentation too:
Like BryanK, I’m also wondering if Windows really duplicates the scan that the BIOS did.
Actually I also wonder if the memory tester in Vista really scans all of memory. After it boots you can see that Vista x64 is using all of the installed memory including discontiguous chunks, but it doesn’t tell you if the tester really scanned it all.
So, looking at what the documentation says, it looks like what really happened was the following:
1. /MAXMEM was implemented using a simple algorithm that does not account for memory “holes”.
2. Now that we fairly routinely have large amounts of memory that include these “holes”, /MAXMEM no longer works correctly.
3. Instead of fixing it, Microsoft simply renamed the switch to hide the problem.
I implemented the /MAXMEM switch. And perhaps it should have been named /IGNOREALLPHYSICALMEMORYABOVETHISBOUNDARY or something similar, but it wasn’t. This was implemented back in the day when 16MB was a LOT of memory. Some PC manufacturers took a few shortcuts. Since nobody would ever put more than 16MB of memory in a PC, they did nasty things like
don’t bother even connecting memory above 16MB, causing everything above 16MB to be an alias for the memory below 16MB
Locate ROM in a window above 16MB, causing small chunks of memory to actually appear to be readable and writable, except when you went to read back what you wrote, it wasn’t there anymore.
To work around all these flavors of brokenness, /MAXMEM was created specifically to ignore all memory above 16MB regardless of whether the BIOS claimed it worked or not.
Later, /MAXMEM was repurposed (perhaps inappropriately) to do quick & dirty performance testing of the OS with different amounts of memory.
Even later, /MAXMEM was repurposed to work around buggy drivers that choked on physical memory addresses > 16MB, 1GB, 2GB, 4GB, etc.
Then people figured out that /MAXMEM didn’t really do what they wanted (because it was never intended to) and /BURNMEMORY was added instead.
Nice one John – that pretty much explains it all. ANy other similar war stories?