How to See Linux' View of the Ram in Order to Determinate the Fragmentation

How to see Linux' view of the RAM in order to determinate the fragmentation


Memory Fragmentation

When a Linux system has been running for a while memory fragmentation can increase which depends heavily on the nature of the applications that are running on it. The more processes allocate and free memory, the quicker memory becomes fragmented. And the kernel may not always be able to defragment enough memory for a requested size on time. If that happens, applications may not be able to allocate larger contiguous chunks of memory even though there is enough free memory available. Starting with the 2.6 kernel, i.e. RHEL4 and SLES9, memory management has improved tremendously and memory fragmentation has become less of an issue.

To see memory fragmentation you can use the magic SysRq key. Simply execute the following command:

# echo m > /proc/sysrq-trigger

This command will dump current memory information to /var/log/messages. Here is an example of a RHEL3 32-bit system:

Jul 23 20:19:30 localhost kernel: 0*4kB 0*8kB 0*16kB 1*32kB 0*64kB 1*128kB 1*256kB 1*512kB 1*1024kB 0*2048kB 0*4096kB = 1952kB)
Jul 23 20:19:30 localhost kernel: 1395*4kB 355*8kB 209*16kB 15*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 12244kB)
Jul 23 20:19:31 localhost kernel: 1479*4kB 673*8kB 205*16kB 73*32kB 21*64kB 847*128kB 473*256kB 92*512kB 164*1024kB 64*2048kB 28*4096kB = 708564kB)

The first line shows DMA memory fragmentation. The second line shows Low Memory fragmentation and the third line shows High Memory fragmentation. The output shows memory fragmentation in the Low Memory area. But there are many large memory chunks available in the High Memory area, e.g. 28 4MB.

If memory information was not dumped to /var/log/messages, then SysRq was not enabled. You can enable SysRq by setting sysrq to 1:

# echo 1 > /proc/sys/kernel/sysrq

Starting with the 2.6 kernel, i.e. RHEL4 and SLES9, you don’t need SysRq to dump memory information. You can simply check /proc/buddyinfo for memory fragmentation.

Here is the output of a 64-bit server running the 2.6 kernel:

# cat /proc/buddyinfo

Node 0, zone DMA 5 4 3 4 3 2 1 0 1 1 2
Node 0, zone Normal 1046 527 128 36 17 5 26 40 13 16 94
# echo m > /proc/sysrq-trigger
# grep Normal /var/log/messages | tail -1
Jul 23 21:42:26 localhost kernel: Normal: 1046*4kB 529*8kB 129*16kB 36*32kB 17*64kB 5*128kB 26*256kB 40*512kB 13*1024kB 16*2048kB 94*4096kB = 471600kB
#

In this example I used SysRq again to show what each number in /proc/buddyinfo is referring to.

Source: http://www.puschitz.com/pblog/

How to see top processes sorted by actual memory usage?

First, repeat this mantra for a little while: "unused memory is wasted memory". The Linux kernel keeps around huge amounts of file metadata and files that were requested, until something that looks more important pushes that data out. It's why you can run:

find /home -type f -name '*.mp3'
find /home -type f -name '*.aac'

and have the second find instance run at ridiculous speed.

Linux only leaves a little bit of memory 'free' to handle spikes in memory usage without too much effort.

Second, you want to find the processes that are eating all your memory; in top use the M command to sort by memory use. Feel free to ignore the VIRT column, that just tells you how much virtual memory has been allocated, not how much memory the process is using. RES reports how much memory is resident, or currently in ram (as opposed to swapped to disk or never actually allocated in the first place, despite being requested).

But, since RES will count e.g. /lib/libc.so.6 memory once for nearly every process, it isn't exactly an awesome measure of how much memory a process is using. The SHR column reports how much memory is shared with other processes, but there is no guarantee that another process is actually sharing -- it could be sharable, just no one else wants to share.

The smem tool is designed to help users better gage just how much memory should really be blamed on each individual process. It does some clever work to figure out what is really unique, what is shared, and proportionally tallies the shared memory to the processes sharing it. smem may help you understand where your memory is going better than top will, but top is an excellent first tool.

Memory fragmentation

As per ISO/IEC 9899:201x -> 7.22.3

The order and contiguity of storage allocated by successive calls to
the aligned_alloc, calloc, malloc, and realloc functions is
unspecified.

A good memory manager will be able to tackle the issue to an extent. However, there are other aspects like data alignment [1] which causes internal fragmentation.

What you could do if you rely on inbuilt memory management?

  1. Use a profiler - say valgrind - with memory check option to find the memory which is not freed after use.
    Example:


     valgrind --leak-check=yes myprog arg1 arg2
  2. Follow good practices. Example - In C++, if you intend others to inherit from your polymorphic class, you may declare its destructor virtual.

  3. Use smart pointers.

Notes:

  1. Internal fragmentation.

  2. If you were to use your own memory management system, you may consider Boehm-Demers-Weiser garbage collector.

  3. Valgrind Instrumentation Framework.

  4. Memory not freed after use will contribute to fragmentation.

Portable way to detect heap fragmentation in c++ at runtime?

Short answer: There is no portable way.

Longer answer: How the heap is implemented and how it works is an implementation detail of your implementation that widely differs between platforms, std libraries, and operating systems. You'll have to create a different version for each implementation - provided, the implementation gives you an API to hook into it. (Which I think should be the case for the three platforms you target.)

How can I programmatically get the amount of memory currently available from C/C++ code?

The message you have shown indicates a failure to allocate memory for a kernel allocation, not a userspace allocation. It is a request for a 4MB (this is what order = 10 means) block of contiguous physical memory. This is a very large kmalloc() request, and it is not surprising that it fails (likely due to memory fragmentation rather than free memory).

You can find out how much free memory is available in /proc/meminfo, however a more detailed summary is available from the kernel log immediately after the backtrace - starting with the line "Mem-info".


Your backtrace shows that there is 16548kB of memory available, but the largest block is 2048kB (order = 9). So memory fragmentation is indeed your problem.

From reading the source to the tsif driver you appear to be using, it seems that the driver requests a kernel allocation with a size entirely controlled by userspace, invoked by the TSIF_REQ_RX_BUF ioctl() (this is a really bad design, especially given that it doesn't even try to report failures to userspace!). My suggestion is to reduce the size of the buffer you are requesting with this ioctl.



Related Topics



Leave a reply



Submit