Avoiding maps fragmentation Was: Leaks in mmap address space: 2.6.11.4

From: Wolfgang Wander
Date: Thu Apr 21 2005 - 09:51:32 EST


Looks like I have to answer myself here with you guys all busy
gitting...

I posted two sample programs last week that showed that large
application can run out of memory a lot quicker on 2.6 than on 2.4.
The reason is that the /proc/*/maps space fragments a lot faster
on 2.6 than with 2.4 kernels.

2.4 started searching for unused space from the mmap base up to the
stack, 2.6 starts search from the end of the last mapped area
(mm->free_area_cache).

The difference in the two algorithms is obvious (apart from the
efficiency which is undoubtedly better in 2.6):

Whereas 2.4 naturally started to fill small holes closer to the base thus
leaving larger areas open towards the stack, 2.6 will place small maps
all over the mappable area thus closing up potential large holes inefficiently.

The attached patch is left as a hack so that you guys can come up (please;-)
with a neater solution but something ought to be done that saves large
holes from small map clutter...

Wolfgang

PS: Patch^H^H^H^H^H Ugly_Hack is against 2.6.11.7 and only 'fixes' the
two architectures I'm interested in (i386 and x86_64)



diff -ru linux-2.6.11.7.orig/arch/x86_64/kernel/sys_x86_64.c linux-2.6.11.7/arch/x86_64/kernel/sys_x86_64.c
--- linux-2.6.11.7.orig/arch/x86_64/kernel/sys_x86_64.c 2005-03-02 02:38:13.000000000 -0500
+++ linux-2.6.11.7/arch/x86_64/kernel/sys_x86_64.c 2005-04-21 09:27:38.000000000 -0400
@@ -112,8 +112,8 @@
(!vma || addr + len <= vma->vm_start))
return addr;
}
- addr = mm->free_area_cache;
- if (addr < begin)
+ /* addr = mm->free_area_cache;
+ if (addr < begin) */
addr = begin;
start_addr = addr;

diff -ru linux-2.6.11.7.orig/mm/mmap.c linux-2.6.11.7/mm/mmap.c
--- linux-2.6.11.7.orig/mm/mmap.c 2005-03-02 02:38:12.000000000 -0500
+++ linux-2.6.11.7/mm/mmap.c 2005-04-21 09:32:06.000000000 -0400
@@ -1173,7 +1173,7 @@
(!vma || addr + len <= vma->vm_start))
return addr;
}
- start_addr = addr = mm->free_area_cache;
+ start_addr = addr = TASK_UNMAPPED_BASE; /* mm->free_area_cache; */

full_search:
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {



Wolfgang Wander writes:
> Here is another program that illustrates the problem which this time
> in C and without using glibc allocation schemes.
>
> ----------------------------------------------------------------------
>
> Wolfgang Wander writes:
> > Hi,
> >
> > we are running some pretty large applications in 32bit mode on 64bit
> > AMD kernels (8GB Ram, Dual AMD64 CPUs, SMP). Kernel is 2.6.11.4 or
> > 2.4.21.
> >
> > Some of these applications run consistently out of memory but only
> > on 2.6 machines. In fact large memory allocations that libc answers
> > with private mmaps seem to contribute to the problem: 2.4 kernels
> > are able to combine these mmaps to large chunks whereas 2.6
> > generates a rather fragmented /proc/self/maps table.
> >
> > The following C++ program reproduces the error (compiled statically
> > on a 32bit machine to get exactly the same executable for 2.4 and
> > 2.6 environments):
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/