Is there a way to detect memory fragmentation on linux ? This is because on some long running servers I have noticed performance degradation and only after I restart process I see better performance. I noticed it more when using linux huge page support -- are huge pages in linux more prone to fragmentation ?

I have looked at /proc/buddyinfo in particular. I want to know whether there are any better ways(not just CLI commands per se, any program or theoretical background would do) to look at it.

link|improve this question
2  
serverfault.com would probably love to help you with this. – msw Apr 16 '10 at 9:11
I am not looking at just quick commandline solutions, any simple program/theory will also do. Hence, I did not ask at serverfault. – Raghu Apr 16 '10 at 9:37
1  
I don't understand here one point. As far as I understand memory fragmentation must lead to lack of memory and as a result to memory allocation errors. However you are asking about performance degradation. Is it because you have lots of memory swapped to disk? And if so what give vmstat in the field so? – skwllsp Apr 16 '10 at 10:49
This does belong on SF, it is a system administration question. I've answered it with insights on how the kernel manages memory, but I am voting to migrate it over to SF. This is not exactly related to programming, its more of a question of how to manage lots of processes that compete for contiguous blocks, or one process that has just outgrown the available physical memory. – Tim Post Apr 16 '10 at 11:14
Disagee. On HP-UX Detecting memory fragmentation in a running program is a job for a software developer and it is done with wdb. There you have to find code what allocates in a way that results in memory fragmentation and change this code. I don't see why on Linux it must be a responsibility of a system administrator. – skwllsp Apr 16 '10 at 11:28
show 6 more comments
feedback

migrated from stackoverflow.com Apr 17 '10 at 4:40

This question came from our site for professional and enthusiast programmers.

2 Answers

I am answering to the linux tag. My answer is specific only to Linux.

Yes, huge pages are more prone to fragmentation. There are two views of memory, the one your process gets (virtual) and the one the kernel manages (real). The larger any page, the more difficult its going to be to group (and keep it with) its neighbors, especially when your service is running on a system that also has to support others that by default allocate and write to way more memory than they actually end up using.

The kernel's mapping of (real) granted addresses is private. There's a very good reason why userspace sees them as the kernel presents them, because the kernel needs to be able to overcommit without confusing userspace. Your process gets a nice, contiguous disneyfied address space in which to work, oblivious of what the kernel is actually doing with that memory behind the scenes.

The reason you see degraded performance on long running servers is most likely because allocated blocks that have not been explicitly locked (i.e. mlock/mlockall or posix_madvise) and not modified in a while have been paged out, which means your service skids to disk when it has to read them. Modifying this behavior makes your process a bad neighbor, which is why many people put their RDBMS on a completely different server than web/php/python/ruby/whatever. The only way to fix that, sanely is to reduce the competition for contiguous blocks.

Fragmentation is only really noticeable (in most cases) when page A is in memory and page B has moved to swap. Naturally, re-starting your service would seem to 'cure' this, but only because the kernel has not yet had an opportunity to page out the process' (now) newly allocated blocks within the confines of its overcommit ratio.

In fact, re-starting (lets say) 'apache' under a high load is likely going to send blocks owned by other services straight to disk. So yes, 'apache' would improve for a short time, but 'mysql' might suffer .. at least until the kernel makes them suffer equally when there is simply a lack of ample physical memory.

Add more memory, or split up demanding malloc() consumers :) Its not just fragmentation that you need to be looking at.

Try vmstat to get an overview of what's actually being stored where.

link|improve this answer
Thank you for the answer. I was using huge pages(size = 2048KB each) for mysql - innodb buffer pool - to see how well it fares(using sysbench). Initially when the process uptime (and even system uptime) was low, it was giving very good results. However, its performance started to degrade over several runs. Regarding the page out you mentioned, I surely noticed a high VM activity, but I presumed it may have been because of benchmark and innodb log flushing(vm activity higher with huge pages than without). I also set vm.swappiness to 1. I could not notice any drastic change. – Raghu Apr 16 '10 at 13:49
feedback

Using huge pages should not cause extra memory fragmentation on Linux; Linux support for huge pages is only for shared memory (via shmget or mmap), and any huge pages used must be specifically requested and preallocated by a system admin. Once in memory, they are pinned there, and are not swapped out. The challenge of swapping in huge pages in the face of memory fragmentation is exactly why they remain pinned in memory (when allocating a 2MB huge page, the kernel must find 512 contiguous free 4KB pages, which may not even exist).

Linux documentation on huge pages: http://lwn.net/Articles/375098/

There is one circumstance where memory fragmentation could cause huge page allocation to be slow (but not where huge pages cause memory fragmentation), and that's if your system is configured to grow the pool of huge pages if requested by an application. If /proc/sys/vm/nr_overcommit_hugepages is greater than /proc/sys/vm/nr_hugepages, this might happen.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.