To view parent comment, click here.
To read all comments associated with this story, please click here.
It really is a pity that an MMU doesn't track pointers within data structures of a user-level process and adjust them when there's no option to getting memory than rearranging all that's allocated within a process to make room for it; if an MMU did do that, then fragmentation truly wouldn't ever be a problem, and life would be so much easier. Here is an experiment to demonstrate that an MMU does not solve the fragmentation issue by an example application that does these things:
1. Create a list of randomly-sized allocated memory blocks, that vary in size from the minimum size of pages allocated by the OS, up to some integer multiple of that number of pages, and record all their addresses. This range needs to be tracked for the upper bounds. This application needs to allocate memory until it cannot allocate more.
2. Go through the list of memory blocks allocated by this, and free every other allocated memory block.
3. This is the proof that an MMU does not solve memory fragmentation: attempt to allocate one or more blocks of memory that are larger than any single allocation made above. This will fail, and it does not matter what programming language, computer hardware, or operating system is used, if it uses an MMU that works in a similar manner to an x86 processor (ie. doesn't do the magic of fixing addresses within virtual address space when things get tight).
Somewhere, somehow, a process either will run into a wall when it comes to fragmentation and will fail to be able to allocate memory, or it will hit the wall, and have to rearrange data within its own address space until it can make a large enough area of free memory for an allocation to succeed, and having an MMU does nothing to make this any easier for anyone. Using handles to refer to ranges of memory that you lock down when you need to use them makes this less fragile than using a virtual address space alone, but is rather tedious, to say the least. This is a method that was used in Windows before Windows NT/95/3.1, among other systems, such as the PalmOS, etc. and is still likely to be used in more limited memory environments. In a way, the Java VM and the Microsoft .NET runtime environment automate all that, and leave the developer to worry about coding the application in a less involved way that doesn't require them to worry as much about memory management, by taking care of all of that for them. This becomes much more important for long-running applications that have dynamic loads where static buffers cannot be allocated, and where the allocation sizes vary over time. Ever wonder why your favorite web browser memory usage climbs over a period of time? They are a great example of memory fragmentation, as well as disk cache fragmentation, because they work with small bits of text mixed with large and randomly-sized graphic files. The best thing you could do for overall system performance when running a web browser is to have their cache files kept on an isolated partition as a result. If your email application uses separate files, the same thing applies. That way, you can maintain a less-fragmented filesystem for everything else with little effort on your part.
Jonathan Thompson
The author doesn't know much about how memory allocation and memory management work these days.
His claims about fragmentation are only true for systems without an MMU and virtual addresses.
He should look up external vs. internal fragmentation.
His claims about fragmentation are only true for systems without an MMU and virtual addresses.
My above statement was a bit harsh, I know. The fragmentation description in the article was a bit to simple. My point is that most applications has no problem with external fragmentation when running in a 32-bit virtual address space. Even less so, in a 64-bit space. The example that were given certainly wouldn't be a problem.
The article should be replaced by the 2 parter by Jonathan Thompson on this message board. This was a great and usable explanation!






Member since:
The author of this post in bold below either doesn't know that much about memory management themselves, or perhaps knows exactly as much as the author of the article, because making the statement "His claims about fragmentation are only true for systems without an MMU and virtual addresses." shows a limited understanding of what the author was saying, along with a limited understanding of what an MMU does for you, and where it does it for you.
And now, a bit of education to erase the ignorance shown in the bold-quoted post below:
An MMU is a piece of hardware that helps manage translations between virtual and physical addresses in a cooperative manner using the OS to decide the gory details. The virtual addresses are what a user-space process sees: the physical address is looked up via the use of some sort of lookup table in RAM that is maintained by a combination of hardware and the OS, and depending on the hardware/OS combination, may track things such as how recently a range of memory was accessed, and whether or not the range of memory (virtual address) is actually in physical RAM (physical address) when a process attempts to access it.
The same physical area of RAM (physical address) that is used by more than one process may occupy more than a single virtual address range (the address a user-level process sees), and, indeed, it is possible to have the same physical area of RAM occupy more than one virtual address space in the same process. Shared libraries are often loaded exactly once into physical memory, and shared amongst many different processes in their virtual address spaces, which has the benefits of saving RAM space, increasing the chance that the needed code will be in the CPU and filesystem/VM cache, etc. and results in much less swapping. Shared libraries may reside in the same logical (user process virtual memory) address in each process, or it may change; that's one of those details that may vary, as described above. Often, there will be a preferred address space (virtual address) in the user process that a shared library is loaded in; this space may not be available, due to fragmentation within the process virtual address space, and the OS will need to load it into some other portion of virtual address space, all while it isn't moved in the physical address space, which is the space that is only of concern to the kernel level code.
There are certain ranges of physical address space in all machines that are not available for normal RAM use, due to being used for such special purposes as system firmware, memory mapped I/O switches, special buffers used for DMA/bus mastering devices, and simply not having physical RAM present, etc. and thus a user process doesn't usually have these areas mapped into their virtual address space. Depending on the machine architecture, these special use memory pages may leave the address space fragmented at the physical level, which is the case that the kernel cares about. If the kernel needs a portion of RAM larger than is available between these special pages for kernel space data, it needs to either break up its data, or (if it can) move the data in currently used physical RAM address space into a more convenient space, and update the MMU data to reflect that for whatever user-level processes use the data in their virtual address spaces; this is completely transparent to the user-level processes. It is important to note that fragmentation is still an issue for the kernel to deal with.
But wait, there's more! EVen though the kernel can move data in and out of physical RAM for both its own process as well as all user-level processes, and this is transparent to the usr-level processes, it still doesn't solve the problem of fragmentation for each user-level process. Sure, they have as much virtual address space as the system allows them, which may be the entire possible virtual address space possible by that processor (not that common, though) and processes don't have to fight for an address space that they can use, as that's all arbitrated by the OS's policy. Ok, so now we've established that user-level processes don't interfere with each other in terms of fragmenting each other's virtual address space, which is all that really matters to a user-level process. Now, we have our processes with their own sandbox to play in. They can ask for a larger sandbox, and also ask to reduce the size of the sandbox after they're done and still play, as long as they don't choose to terminate. However, this does absolutely nothing for avoiding fragmentation by itself. The smallest amount of memory a process can request from the OS and have it handed to it is in exact multiples of the MMU memory page size (which is most commonly 4K bytes for the x86, 32 bits and less; this varies from processor to processor, and also on the OS) which may not even be a single VM page; Windows NT doesn't allocate anything smaller to a user-level process than increments of 64K bytes, for example, and observation is that BeOS 5.03 is the same in that regard. Each of these OS-level memory allocations may be further subdivided and managed by language-specific memory allocation libraries, such as malloc/free and new/delete for C/C++. When going through a language-specific library that abstracts the OS calls from the user-level process, it may never return unused (by the process) pages of memory that the process has released via free/delete, and keep it within its own heap management for further use, for as long as that process exists. IF those pages are returned to the system, the OS can reassign them to the same process at the same virtual address, or to any other process at any other virtual address, or both. There will then be a hole in the virtual address space of the process that returned that page or group of pages to the OS, however. When that process needs to allocate memory for something, it may ask for something larger than the virtual address space has a hole that is currently unused as assigned by the OS, and it may also be asking for something larger than what is available in the RAM already managed by the library and is present in the virtual address space, and the memory allocation will fail.