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?
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
Follow good practices. Example - In C++, if you intend others to inherit from your polymorphic class, you may declare its destructor virtual.
Use smart pointers.
Notes:
Internal fragmentation.
If you were to use your own memory management system, you may consider Boehm-Demers-Weiser garbage collector.
Valgrind Instrumentation Framework.
- 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
Linux, Where Are the Return Codes Stored of System Daemons and Other Processes
Stty Serial Port Settings for Parity Not Persistent
How to Tar Certain File Types in All Subdirectories
How to Find Files Recursively by File Type and Copy Them to a Directory
Backing Up (And Restoring) a Plone Instance
Unable to Pass Wget a Variable with Quotes Inside the Variable
Eclipse Cdt Indexer Lost After System Update
How to Diff Directories Over Ssh
What's the Difference Between Event-Driven and Asynchronous? Between Epoll and Aio
Automatic Login on Angstrom Linux
Embedding the Password in the Bash Script
Amazon Linux: "Apt-Get: Command Not Found"
Compile/Run Assembler in Linux
Mount Remote Windows Share from Centos
How to Retain Docker Alpine Container After "Exit" Is Used
How to Parse Netstat Command in Order to Get Process Name and Pid from It
Why Is Gdb Breakpoint Set at the Wrong Address for an X86 Assembly Function