This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2] Allow shrinking of arena heaps using mmap based onovercommit settings when available
- From: Siddhesh Poyarekar <siddhesh at redhat dot com>
- To: Roland McGrath <roland at hack dot frob dot com>
- Cc: KOSAKI Motohiro <kosaki dot motohiro at gmail dot com>, "Carlos O'Donell"<carlos at systemhalted dot org>, Rich Felker <dalias at aerifal dot cx>, libc-alpha at sourceware dot org
- Date: Tue, 11 Sep 2012 15:40:36 +0530
- Subject: Re: [PATCH v2] Allow shrinking of arena heaps using mmap based onovercommit settings when available
- References: <20120720223800.GB26330@sunsite.ms.mff.cuni.cz><20120721133217.GY544@brightrain.aerifal.cx><20120725183634.E0C5F2C0B1@topped-with-meat.com><CAHGf_=qCMy6K1MD4miN65GkMSumYTtH23xoFrfmCuh=WjybAVA@mail.gmail.com><20120730230006.355f9b67@spoyarek><5016D012.5000101@gmail.com><20120730191758.GX544@brightrain.aerifal.cx><CAHGf_=rRm4B4YCZKgos5hWN_QTYV76fAxcegO7D3x=4_A88Rvw@mail.gmail.com><20120731132705.GZ544@brightrain.aerifal.cx><CAHGf_=pN3KJGL_V1tQ2+o0=-RY4q2du7PJDnak9y7xyzYiH1tQ@mail.gmail.com><20120810235226.408e3cec@spoyarek><CADZpyiz05WnMqrREEtSs+oW_0Ld6hnfxbmFMk_hKYL-P_gFTag@mail.gmail.com><20120811205228.42ab905f@spoyarek><CADZpyizkMLBGK13-h-YH_CpVgbcx3n7gbxYAwxzsdbiEJOMNjg@mail.gmail.com><50289F84.9060205@gmail.com><20120822000610.6110da3f@spoyarek><20120822141946.7702d182@spoyarek><20120823205321.A03E02C0FB@topped-with-meat.com><20120824205628.552958b6@spoyarek><20120907165911.6A8232C0D0@topped-with-meat.com>
Hi Roland,
Here is an updated patch with further fixes as per your review. No
regressions in the testsuite. Also, I have tested this on F16 x86_64 as
follows:
* echo 0 > /proc/sys/vm/overcommit_memory
* Run the benchmark program that I posted earlier:
http://sourceware.org/ml/libc-alpha/2012-08/msg00462.html
and attach an strace as follows:
strace -f -e madvise -p $(pgrep a.out)
to confirm that madvise is being called. Detach and attach strace again
as follows:
strace -f -e mmap -p $(pgrep a.out)
to ensure that there are no mmap calls with MAP_FIXED.
Now disable overcommit:
* echo 2 > /proc/sys/vm/overcommit_memory
* Run the benchmark program and verify that the behaviour is the
opposite, i.e. there should be no calls to madvise and you should see
calls to mmap with MAP_FIXED.
Further, I also verified that I see the performance difference between
madvise and MAP_FIXED:
with overcommit_memory == 0:
RUNS=4096, TOTAL=8859615.000000, AVG=2162.991943
RUNS=4096, TOTAL=8948967.000000, AVG=2184.806396
RUNS=4096, TOTAL=9002337.000000, AVG=2197.836182
RUNS=4096, TOTAL=9147284.000000, AVG=2233.223633
RUNS=4096, TOTAL=8852469.000000, AVG=2161.247314
RUNS=4096, TOTAL=8920974.000000, AVG=2177.972168
RUNS=4096, TOTAL=9051495.000000, AVG=2209.837646
RUNS=4096, TOTAL=8896417.000000, AVG=2171.976807
with overcommit_memory == 2:
RUNS=4096, TOTAL=9916217.000000, AVG=2420.951416
RUNS=4096, TOTAL=10098292.000000, AVG=2465.403320
RUNS=4096, TOTAL=9951147.000000, AVG=2429.479248
RUNS=4096, TOTAL=9776165.000000, AVG=2386.759033
RUNS=4096, TOTAL=9735272.000000, AVG=2376.775391
RUNS=4096, TOTAL=10049977.000000, AVG=2453.607666
RUNS=4096, TOTAL=9967350.000000, AVG=2433.435059
RUNS=4096, TOTAL=9817866.000000, AVG=2396.939941
Regards,
Siddhesh
ChangeLog:
* malloc/arena.c: Include malloc-sysdep.h.
(shrink_heap): Use check_may_shrink_heap to decide if madvise
is sufficient to shrink the heap or an unmap is needed.
* sysdeps/generic/malloc-sysdep.h: New file. Define
new function check_may_shrink_heap.
* sysdeps/unix/sysv/linux/malloc-sysdep.h: New file. Define
new function check_may_shrink_heap.
diff --git a/malloc/arena.c b/malloc/arena.c
index 97c0b90..50f3f96 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -19,6 +19,9 @@
#include <stdbool.h>
+/* Get the implementation for check_may_shrink_heap. */
+#include <malloc-sysdep.h>
+
/* Compile-time constants. */
#define HEAP_MIN_SIZE (32*1024)
@@ -621,9 +624,9 @@ shrink_heap(heap_info *h, long diff)
new_size = (long)h->size - diff;
if(new_size < (long)sizeof(*h))
return -1;
- /* Try to re-map the extra heap space freshly to save memory, and
- make it inaccessible. */
- if (__builtin_expect (__libc_enable_secure, 0))
+ /* Try to re-map the extra heap space freshly to save memory, and make it
+ inaccessible. See malloc-sysdep.h to know when this is true. */
+ if (__builtin_expect (check_may_shrink_heap (), 0))
{
if((char *)MMAP((char *)h + new_size, diff, PROT_NONE,
MAP_FIXED) == (char *) MAP_FAILED)
diff --git a/sysdeps/generic/malloc-sysdep.h b/sysdeps/generic/malloc-sysdep.h
new file mode 100644
index 0000000..bbc48c0
--- /dev/null
+++ b/sysdeps/generic/malloc-sysdep.h
@@ -0,0 +1,25 @@
+/* System-specific malloc support functions. Generic version.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Force an unmap when the heap shrinks in a secure exec. This ensures that
+ the old data pages immediately cease to be accessible. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ return __libc_enable_secure;
+}
diff --git a/sysdeps/unix/sysv/linux/malloc-sysdep.h b/sysdeps/unix/sysv/linux/malloc-sysdep.h
new file mode 100644
index 0000000..f926aea
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/malloc-sysdep.h
@@ -0,0 +1,57 @@
+/* System-specific malloc support functions. Linux version.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <not-cancel.h>
+
+/* The Linux kernel overcommits address space by default and if there is not
+ enough memory available, it uses various parameters to decide the process to
+ kill. It is however possible to disable or curb this overcommit behavior
+ by setting the proc sysctl vm.overcommit_memory to the value '2' and with
+ that, a process is only allowed to use the maximum of a pre-determined
+ fraction of the total address space. In such a case, we want to make sure
+ that we are judicious with our heap usage as well, and explicitly give away
+ the freed top of the heap to reduce our commit charge. See the proc(5) man
+ page to know more about overcommit behavior.
+
+ Other than that, we also force an unmap in a secure exec. */
+static inline bool
+check_may_shrink_heap (void)
+{
+ static int may_shrink_heap = -1;
+
+ if (__builtin_expect (may_shrink_heap >= 0, 1))
+ return may_shrink_heap;
+
+ may_shrink_heap = __libc_enable_secure;
+
+ if (__builtin_expect (may_shrink_heap == 0, 1))
+ {
+ int fd = open_not_cancel_2 ("/proc/sys/vm/overcommit_memory",
+ O_RDONLY | O_CLOEXEC);
+ if (fd >= 0)
+ {
+ char val;
+ ssize_t n = read_not_cancel (fd, &val, 1);
+ may_shrink_heap = n > 0 && val == '2';
+ close_not_cancel_no_status (fd);
+ }
+ }
+
+ return may_shrink_heap;
+}