I am learning from here about Windows 32-bit virtual memory page mapping,
(I am targeting modern Windows versions, like Vista, Win 7, Server 2003/2008 32-bit versions.)
http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx
Two confusions,
user space virtual memory space is limited to 2G normally, but physical disk page storage could be much larger than 2G. Since there are more disk pages than virtual memory pages, so in theory more than one disk pages could be mapped to one virtual address page. If user request to access some virtual address, how did memory manager know which disk page should be accessed if more than one disk pages are mapped to one virtual address page?
I do not know why there is restrictions like byte[] array must use continuous virtual memory space. I think in theory even if we only allocate 500M virtual space address, we can re-use such virtual space address to continue to map/unmap disk page file to consume as much as we want, even larger than 2G.
Any ideas?
byte (or any other) arrays must use contiguous address space, in this case contiguous virtual address space.
This is an area that can make fragmentation becomes an issue, and is actually exacerbated by virtualization of memory. Since the various 'redirections' inherent in a such a system system and the performance considerations in making it efficient lead to actual allocation of physical address space mapped to virtual address space in chunks (commonly pages).
So requesting a 10 byte chunk of virtual address space might actually lead to a whole 4K page being reserved and mapped. Since the physical memory within the page must be contiguous this can lead to a whole 4K of virtual address space being 'blocked off'.
Multiple small allocations can be placed within one page (and good memory managers will try to achieve this) but none the less address space has in effect been reserved over and above what was strictly required. Consider the allocation of a single byte at the start f a page, then 4K - 2 bytes followed by another single byte. This occupies (efficiently) the whole page.
Consider if the middle allocation is no longer necessary, and is thus freed. Until the 'top' and 'tail' values are either freed or moved elsewhere a gap has been created in the virtual address space which can only be filled by something < 4K-1 bytes in size.
If sufficient of these sorts of things occur the contiguous regions in virtual address space shrink much faster than the actual total really used memory does.
You are correct in that there is nothing stopping you, the user, mapping your (limited in 32bit land) address space to the much larger disk or memory space that the CPU/OS supports . Some chips make this possible with more than 4GB of physical address space via mechanisms like PAE.
Windows itself provides an API to deal with most aspects of 'changing the mapping of your address space to get a different 'window' onto a wider pool (be it via things like PAE, running WoW64, disk or a mixture). This is called AWE. But mechanisms like this have existed for years (as those who remember the days of EMS with conventional memory or indeed the days of segmented memory.
Even without CPU and OS support you can still do it yourself by hand by a variety of techniques (see below).
A great deal of the more complex aspects of this in windows were dealt with by ever interesting Raymond Chen.
- A useful list of the relevant articles
- He follows it up with some specifics and links to how you can actually allocate more than 2GB of memory
- Also worth remembering is that you aren't the only person consuming address space in your process
(There is a switch for some versions of Windows to enable 3G for user programs, but we'll ignore that for purposes of this discussion, since the principle is the same.)
32bit programs can only access 4G of memory, since that's the largest pointer you can fit in 32 bits. When a program runs, some of the memory space is mapped to itself, and some is mapped into the operating system. Otherwise, when you call into the operating system, the operating system code couldn't see both its own memory and the program memory at the same time.
So your program doesn't get all of the memory, and hence the restrictions on contiguous allocation.
Now, different programs can have different subsets of all of the addressable memory. Some 32bit chips allow physically more than 4G of memory, but still, any given process, since it's 32bits, can only "see" directly up to 32bits-worth, or 4G, at a time, some of which belongs to the process (2G), and some to the operating system (2G) for managing the program and other programs.
That's as simple an explanation as I can give; see Virtual Memory for a longer and more technical explanation.
Mark Russinovich wrote good article Pushing the Limits of Windows: Virtual Memory. I think you should read it to clearly understand how it is works.
The total virtual address space available to a process is 4GB. The upper 2GB of this is common to all processes and is accessible only to system level components. The lower 2GB is private to each process, it is not shared. This has absolutely nothing to do with the size of RAM. There can be far more than 2GB of disk pages mapped to user processes. Since the 2GB process space is private the total address space for all processes will be far more than 2GB. It is impossible, even in theory, for more than one disk page to be mapped to one virtual address in the same process.