Memory fragmentation troubleshooting

This article provides elementary overview of the buddy allocation algorithm, memory fragmentation issues it introduces, and how to obtain some more insight on this in Linux.

To allocate dynamic memory to the process’s data segment (heap), malloc() in Linux uses the buddy allocation algorithm — data segment is divided into power-of-two partitions, and it satisfies allocations returning the partition that is closest fit to the requested size. So, the buddy system organizes free memory in blocks of various orders. For order 0, 1, 2, …, 9 it has lists of areas containing 2^order pages. If a small area is needed and only a larger area is available, the larger area is split into two halves (buddies), possibly repeatedly. This algorithm is simple and fast, but introduces fragmentation.

  • Internal fragmentation: occurs when more memory than requested is used to satisfy an allocation (inefficient use of available memory)
  • External fragmentation: occurs when sufficient memory is free to satisfy a request, but it is split into two or more nonadjacent chunks (inefficient use of memory or failed memory allocations)

The number of free areas of each order can be seen in /proc/buddyinfo. External fragmentation is a problem under some workloads, and buddyinfo is useful for helping diagnose these problems. /proc/buddyinfo will give you a clue as to how big is an area you can safely allocate, or why a previous allocation failed.

$ cat /proc/buddyinfo 
Node 0, zone      DMA      2      0      1      1      1      1      2      1      1      1      2 
Node 0, zone    DMA32      7     13      7      2      1      6      6     21     14      7    196

Each column represents the number of pages of a certain order which are available. In this case, there are 2 chunks of 2^0*PAGE_SIZE available in zone DMA, 0 chunks of 2^1*PAGE_SIZE in zone DMA, etc.

Furthermore, to dump memory information to /var/log/messages execute the following:

$ echo m > /proc/sysrq-trigger

Here’s a part of this output related to memory fragmentation:

Jun 12 21:39:13 pawwa kernel: Node 0 DMA: 2*4kB 0*8kB 1*16kB 1*32kB 1*64kB 1*128kB 2*256kB 1*512kB 1*1024kB 1*2048kB 2*4096kB = 12536kB
Jun 12 21:39:13 pawwa kernel: Node 0 DMA32: 69*4kB 53*8kB 24*16kB 6*32kB 2*64kB 2*128kB 4*256kB 21*512kB 14*1024kB 7*2048kB 196*4096kB = 844924kB

I’ve seen that under some heavy workloads, network packets might be dropped due to fragmentation issues and page allocation failures. In order to try to get the fragmentation under control, even for a little while, a course of action might be to identify if there’s a high slab use by running slabtop, and if there’s high dentry and inode cache try to drop those:

$ echo 3 > /proc/sys/vm/drop_caches

Sources

  • https://www.kernel.org/doc/Documentation/filesystems/proc.txt
  • https://www.kernel.org/doc/Documentation/vm/pagemap.txt
  • http://www.win.tue.nl/~aeb/linux/lk/lk-9.html
  • http://en.wikipedia.org/wiki/Buddy_memory_allocation
  • https://www.kernel.org/doc/Documentation/sysctl/vm.txt
  • http://www.redhat.com/f/pdf/summit/dshakshober_1010_part_1_performance_analysis.pdf

Comments are closed.