Address-space monitoring
17/12/06 23:04 |
Software
I've recently been trying to understand the
memory-allocation policy that OSX uses. I was getting
'vm_allocate failure' messages on the console, for
one of my apps which is generally not a good thing.
The app in question uses a *lot* of memory
temporarily, over and over again. It can allocate and
free large chunks of memory (say 100 to 200 MBytes at
a time) depending on what the user is doing. "top"
was telling me I was using about 1GB of RAM in the
steady-state, and with 4GB in the machine, I wanted
to know why I couldn't allocate another 200MB.
It turns out that I was suffering from memory-fragmentation. Even a relatively small request (anything more than a single page) will allocate from the set of 'large' memory regions for the application in its address space. The pairing of genuinely large allocations (the above mentioned 100-200 chunks) and smaller allocations meant that memory-regions weren't being freed back to the OS, even though I had called 'free' on the large chunk of RAM. As far as the OS was concerned, I'd freed my memory just fine, but the VM system still had me using the region because there were other allocations within that region.
This is counter-intuitive (but completely obvious when you think about it :-). Only memory-regions that are completely empty (ie: all allocated pages within the region have been freed) will be returned to the OS. Until that time, even though the OS will tell you that memory is available, it really isn't, until the memory-region in which that memory was allocated is completely empty.
I wrote a small tool to display the output of 'vmstat' (because I found it hard to visualise). If anyone wants it, I've made it available as a DMG containing the source project. You can specify the program to monitor, and either take snapshots or periodically sample it. The entire 4GB of address-space is shown as 1 page per pixel (so 1024x1024 pixels) starting in the lower left corner. Clicking or dragging the mouse over allocated pixels will give more details on the allocation.
Perhaps it'll be useful to someone else :-)
It turns out that I was suffering from memory-fragmentation. Even a relatively small request (anything more than a single page) will allocate from the set of 'large' memory regions for the application in its address space. The pairing of genuinely large allocations (the above mentioned 100-200 chunks) and smaller allocations meant that memory-regions weren't being freed back to the OS, even though I had called 'free' on the large chunk of RAM. As far as the OS was concerned, I'd freed my memory just fine, but the VM system still had me using the region because there were other allocations within that region.
This is counter-intuitive (but completely obvious when you think about it :-). Only memory-regions that are completely empty (ie: all allocated pages within the region have been freed) will be returned to the OS. Until that time, even though the OS will tell you that memory is available, it really isn't, until the memory-region in which that memory was allocated is completely empty.
I wrote a small tool to display the output of 'vmstat' (because I found it hard to visualise). If anyone wants it, I've made it available as a DMG containing the source project. You can specify the program to monitor, and either take snapshots or periodically sample it. The entire 4GB of address-space is shown as 1 page per pixel (so 1024x1024 pixels) starting in the lower left corner. Clicking or dragging the mouse over allocated pixels will give more details on the allocation.
Perhaps it'll be useful to someone else :-)