From: Praveen Rao (psrao_at_windows.microsoft.com)
Date: Thu Feb 12 2004 - 00:32:04 PST
This paper discusses Virtual Memory implementation in VAX/VMS.
VAX has a byte-addressable 32-bit virtual address space divided in 512
byte pages. The page is basic unit of mapping and protection. The
address space of a process is divided into P0, P1, P2 regions each 1GB.
P2 is the system address space that is shared between all processes.
Each of these regions has its own page table. Each page table has an
associated base register and length register in the hardware. The base
register of system page table contains the physical address of the page
table while base registers for P0 and P1 regions (which are in user
space) have virtual address of the respective page tables.
P0 and P1 page tables can themselves be paged out.
P0 region contains user's program and heap that grows towards higher
addresses. The first page is reserved to make a NULL pointer cause an
exception. P1 region contains user stack that grows towards the lower
addresses. P1 region also contains a fixed size executive stack for the
process and executive data for the process.
Memory management system is divided into a pager (that pages, pages in
and out of memory) and swapper (that pages in or out the whole process).
The pager makes careful considerations to reduce inefficiencies caused
by heavy faulting. It uses a local page replacement policy which limits
the number of pages that are resident in the memory for a process. For
each process pager maintains a data structure called resident set.
Initially when a program starts its resident set is empty and as it
references pages, pages are faulted in. When the resident set limit is
reached, the process needs to release a page to accommodate a new page.
The pager uses simple FIFO replacement policy. Referenced bit tracking
of pages was not used due to concerns of computations required for this
for programs with a large number of pages.
This scheme still carries over to NT, though the assumptions at the time
of paper (trade-off memory usage for processor time) do not seem
appropriate with modern processors.
The design uses some clever optimizations to reduce I/O activity caused
by paging.
1) Caching of pages: The system uses free and modified lists of pages.
When a page is removed from process's resident set, it is moved to free
list if it was not modified and to the modified list if it was modified.
When a new resident page is needed for the process (e.g. when read from
disk) the head of the free list is used. Free and modified lists work as
caches of clean and dirty pages. If the process references these pages
again they can be moved to the resident list cheaply avoiding expensive
disk activity. It also means that writes to the same page will get
clustered. This reduces the page faults tremendously and moves the
simply FIFO algorithm close to the most optimal, i.e. LRU algorithm in
terms of lowering page faults.
2) Clustering of pages: When the pages are faulted in, the pager tries
to bring in multiple pages to memory in a single I/O operation and
similarly writes the pages to disk only after limit is reached for
number of modified pages (this limit is set around 100). As an added
optimization, pager searches for virtually contiguous pages and writes
them on contiguous paging file blocks. This in turn facilitates
clustering when these pages are read back. During read, pager looks at
blocks on the disk after and before the current block to see if there
are relevant pages that can be clustered in a single I/O operation.
Executable images, for example, are written by linker in contiguous
bytes as far as possible - so this reduces the startup time of a
program.
The paper shows numbers that show improvements caused by these
optimizations.
Paging for system spaces works in a similar fashion except that page
tables for user processes (which are maintained in system space) are not
eligible for removal from a process's resident set as long as they
contain valid page table entries. They are swapped out with the process
though if the whole process is swapped out.
The swapper load a process a swapped out process in memory if the entire
resident set of the process can be loaded.
The system also gives control to user processes to expand their P0, P1
regions, to increase/decrease resident size, to lock/unlock pages in
memory, create/map a global/private section into process address space
and to produce a record of page-fault activity.
It was a very nice and succinct summary of memory management in VAX/VMS.
Since the same overall design is used in NT, it improvement my
understanding of memory management of NT tremendously which is very
relevant to me. Some of the assumptions/design decisions may not be
appropriate for NT anymore in modern days - for example, it can
incorporate a global page replacement policy.
This archive was generated by hypermail 2.1.6 : Thu Feb 12 2004 - 00:32:07 PST