summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2018-05-09 15:44:35 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2018-05-09 15:44:35 +0100
commit7d0567ac84c97e5357b8997a4c9e4fa7541c917b (patch)
tree023899e388a790fbd9764a5408a4e799a431fb74
parent3d2ab4680dd056e0731220fa387cc79456ae01cc (diff)
downloadglib-slice-jemalloc.tar.gz
Allow replacing the GSlice allocator with jemallocslice-jemalloc
The jemalloc allocator implementation comes from the BSD world, and it's used in various places, including: * Mozilla * Rust * Android * Cassandra * MariaDB * Redis More info: http://jemalloc.net Currently, support is enabled by default on Linux, but you have to opt in using `G_SLICE=use-jemalloc`.
-rw-r--r--configure.ac24
-rw-r--r--glib-2.0.pc.in2
-rw-r--r--glib/Makefile.am4
-rw-r--r--glib/gslice.c87
-rw-r--r--glib/gslice.h3
5 files changed, 101 insertions, 19 deletions
diff --git a/configure.ac b/configure.ac
index 823c45bda..bc3e0645c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -130,6 +130,7 @@ case "$host" in
glib_dir_separator='\\\\'
glib_searchpath_separator=';'
glib_cv_stack_grows=no
+ glib_jemalloc_default=no
# Unfortunately the mingw implementations of C99-style snprintf and vsnprintf
# don't seem to be quite good enough, at least not in mingw-runtime-3.14.
# (Sorry, I don't know exactly what is the problem, but it is related to
@@ -155,6 +156,7 @@ case "$host" in
glib_pollfd_format='%d'
glib_dir_separator='/'
glib_searchpath_separator=':'
+ glib_jemalloc_default=yes
;;
esac
case $host in
@@ -256,6 +258,10 @@ AC_ARG_ENABLE(mem_pools,
[AS_HELP_STRING([--disable-mem-pools],
[disable all glib memory pools])],,
[disable_mem_pools=no])
+AC_ARG_ENABLE(jemalloc,
+ [AS_HELP_STRING([--disable-jemalloc],
+ [disable jemalloc])],,
+ [enable_jemalloc="$glib_jemalloc_default"])
GLIB_TESTS
@@ -273,6 +279,24 @@ AS_IF([test "x$disable_mem_pools" = "xno"], [
AC_MSG_RESULT([yes])
])
+PKG_CHECK_MODULES(JEMALLOC, [jemalloc], [has_jemalloc=yes], [has_jemalloc=no])
+AC_MSG_CHECKING([whether jemalloc should be used in GSlice])
+AS_IF([test "x$enable_jemalloc" = xyes], [
+ AS_IF([test "x$has_jemalloc" = xyes], [
+ AC_DEFINE(ENABLE_JEMALLOC, 1, [Whether to enable jemalloc as the GSlice allocator])
+ AC_MSG_RESULT([yes])
+ JEMALLOC_REQUIRES="jemalloc"
+ ], [
+ AC_MSG_ERROR([jemalloc is not available])
+ ])
+], [
+ AC_MSG_RESULT([no])
+ JEMALLOC_REQUIRES=""
+])
+AC_SUBST(JEMALLOC_CFLAGS)
+AC_SUBST(JEMALLOC_LIBS)
+AC_SUBST(JEMALLOC_REQUIRES)
+
dnl location to install runtime libraries, e.g. ../../lib to install
dnl to /lib if libdir is /usr/lib
AC_ARG_WITH(runtime-libdir,
diff --git a/glib-2.0.pc.in b/glib-2.0.pc.in
index 275fc0163..e9ffabfff 100644
--- a/glib-2.0.pc.in
+++ b/glib-2.0.pc.in
@@ -10,7 +10,7 @@ glib_mkenums=glib-mkenums
Name: GLib
Description: C Utility Library
Version: @VERSION@
-Requires.private: @PCRE_REQUIRES@
+Requires.private: @PCRE_REQUIRES@ @JEMALLOC_REQUIRES@
Libs: -L${libdir} -lglib-2.0 @INTLLIBS@
Libs.private: @G_THREAD_LIBS@ @G_LIBS_EXTRA@ @PCRE_LIBS@ @INTLLIBS@ @ICONV_LIBS@ @CARBON_LIBS@ @COCOA_LIBS@
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include @GLIB_EXTRA_CFLAGS@
diff --git a/glib/Makefile.am b/glib/Makefile.am
index 8da549c7f..ae25cedff 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -351,8 +351,8 @@ pcre_lib = pcre/libpcre.la
pcre_inc =
endif
-libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS)
-libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS)
+libglib_2_0_la_CFLAGS = $(AM_CFLAGS) $(GLIB_HIDDEN_VISIBILITY_CFLAGS) $(LIBSYSTEMD_CFLAGS) $(JEMALLOC_CFLAGS)
+libglib_2_0_la_LIBADD = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ @ICONV_LIBS@ @G_LIBS_EXTRA@ $(pcre_lib) $(G_THREAD_LIBS_EXTRA) $(G_THREAD_LIBS_FOR_GTHREAD) $(LIBSYSTEMD_LIBS) $(JEMALLOC_LIBS)
libglib_2_0_la_DEPENDENCIES = libcharset/libcharset.la $(printf_la) @GIO@ @GSPAWN@ @PLATFORMDEP@ $(glib_win32_res) $(glib_def)
libglib_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \
diff --git a/glib/gslice.c b/glib/gslice.c
index 6b0f22687..87330a49b 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -19,6 +19,12 @@
#include "config.h"
#include "glibconfig.h"
+#ifdef ENABLE_JEMALLOC
+/* Do not demangle; it's cleaner to use the je_* API */
+# define JEMALLOC_NO_DEMANGLE
+# include <jemalloc/jemalloc.h>
+#endif
+
#if defined HAVE_POSIX_MEMALIGN && defined POSIX_MEMALIGN_WITH_COMPLIANT_ALLOCS
# define HAVE_COMPLIANT_POSIX_MEMALIGN 1
#endif
@@ -238,6 +244,7 @@ typedef struct {
} ThreadMemory;
typedef struct {
gboolean always_malloc;
+ gboolean use_jemalloc;
gboolean bypass_magazines;
gboolean debug_blocks;
gsize working_set_msecs;
@@ -286,6 +293,7 @@ static gsize sys_page_size = 0;
static Allocator allocator[1] = { { 0, }, };
static SliceConfig slice_config = {
FALSE, /* always_malloc */
+ FALSE, /* use_jemalloc */
FALSE, /* bypass_magazines */
FALSE, /* debug_blocks */
15 * 1000, /* working_set_msecs */
@@ -304,6 +312,9 @@ g_slice_set_config (GSliceConfig ckey,
case G_SLICE_CONFIG_ALWAYS_MALLOC:
slice_config.always_malloc = value != 0;
break;
+ case G_SLICE_CONFIG_USE_JEMALLOC:
+ slice_config.use_jemalloc = value != 0;
+ break;
case G_SLICE_CONFIG_BYPASS_MAGAZINES:
slice_config.bypass_magazines = value != 0;
break;
@@ -323,6 +334,8 @@ g_slice_get_config (GSliceConfig ckey)
{
case G_SLICE_CONFIG_ALWAYS_MALLOC:
return slice_config.always_malloc;
+ case G_SLICE_CONFIG_USE_JEMALLOC:
+ return slice_config.use_jemalloc;
case G_SLICE_CONFIG_BYPASS_MAGAZINES:
return slice_config.bypass_magazines;
case G_SLICE_CONFIG_WORKING_SET_MSECS:
@@ -372,6 +385,9 @@ slice_config_init (SliceConfig *config)
const GDebugKey keys[] = {
{ "always-malloc", 1 << 0 },
{ "debug-blocks", 1 << 1 },
+#ifdef ENABLE_JEMALLOC
+ { "use-jemalloc", 1 << 2 },
+#endif
};
flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
@@ -379,6 +395,8 @@ slice_config_init (SliceConfig *config)
config->always_malloc = TRUE;
if (flags & (1 << 1))
config->debug_blocks = TRUE;
+ if (flags & (1 << 2))
+ config->use_jemalloc = TRUE;
}
else
{
@@ -389,7 +407,10 @@ slice_config_init (SliceConfig *config)
* valgrind just by setting G_SLICE to the empty string.
*/
if (RUNNING_ON_VALGRIND)
- config->always_malloc = TRUE;
+ {
+ config->always_malloc = TRUE;
+ config->use_jemalloc = FALSE;
+ }
}
}
@@ -429,7 +450,7 @@ g_slice_init_nomessage (void)
/* we can only align to system page size */
allocator->max_page_size = sys_page_size;
#endif
- if (allocator->config.always_malloc)
+ if (allocator->config.always_malloc || allocator->config.use_jemalloc)
{
allocator->contention_counters = NULL;
allocator->magazines = NULL;
@@ -449,7 +470,7 @@ g_slice_init_nomessage (void)
magazine_cache_update_stamp();
/* values cached for performance reasons */
allocator->max_slab_chunk_size_for_magazine_cache = MAX_SLAB_CHUNK_SIZE (allocator);
- if (allocator->config.always_malloc || allocator->config.bypass_magazines)
+ if (allocator->config.always_malloc || allocator->config.bypass_magazines || allocator->config.use_jemalloc)
allocator->max_slab_chunk_size_for_magazine_cache = 0; /* non-optimized cases */
}
@@ -460,6 +481,9 @@ allocator_categorize (gsize aligned_chunk_size)
if (G_LIKELY (aligned_chunk_size && aligned_chunk_size <= allocator->max_slab_chunk_size_for_magazine_cache))
return 1; /* use magazine cache */
+ if (allocator->config.use_jemalloc)
+ return 3;
+
if (!allocator->config.always_malloc &&
aligned_chunk_size &&
aligned_chunk_size <= MAX_SLAB_CHUNK_SIZE (allocator))
@@ -1021,6 +1045,12 @@ g_slice_alloc (gsize mem_size)
mem = slab_allocator_alloc_chunk (chunk_size);
g_mutex_unlock (&allocator->slab_mutex);
}
+#ifdef ENABLE_JEMALLOC
+ else if (acat == 3)
+ {
+ mem = je_malloc (mem_size);
+ }
+#endif
else /* delegate to system malloc */
mem = g_malloc (mem_size);
if (G_UNLIKELY (allocator->config.debug_blocks))
@@ -1129,6 +1159,14 @@ g_slice_free1 (gsize mem_size,
slab_allocator_free_chunk (chunk_size, mem_block);
g_mutex_unlock (&allocator->slab_mutex);
}
+#ifdef ENABLE_JEMALLOC
+ else if (acat == 3)
+ {
+ if (G_UNLIKELY (g_mem_gc_friendly))
+ memset (mem_block, 0, mem_size);
+ je_free (mem_block);
+ }
+#endif
else /* delegate to system malloc */
{
if (G_UNLIKELY (g_mem_gc_friendly))
@@ -1219,18 +1257,37 @@ g_slice_free_chain_with_offset (gsize mem_size,
}
g_mutex_unlock (&allocator->slab_mutex);
}
- else /* delegate to system malloc */
- while (slice)
- {
- guint8 *current = slice;
- slice = *(gpointer*) (current + next_offset);
- if (G_UNLIKELY (allocator->config.debug_blocks) &&
- !smc_notify_free (current, mem_size))
- abort();
- if (G_UNLIKELY (g_mem_gc_friendly))
- memset (current, 0, mem_size);
- g_free (current);
- }
+#ifdef ENABLE_JEMALLOC
+ else if (acat == 3)
+ {
+ while (slice)
+ {
+ guint8 *current = slice;
+ slice = *(gpointer*) (current + next_offset);
+ if (G_UNLIKELY (allocator->config.debug_blocks) &&
+ !smc_notify_free (current, mem_size))
+ abort();
+ if (G_UNLIKELY (g_mem_gc_friendly))
+ memset (current, 0, mem_size);
+ je_free (current);
+ }
+ }
+#endif
+ else
+ {
+ /* delegate to system malloc */
+ while (slice)
+ {
+ guint8 *current = slice;
+ slice = *(gpointer*) (current + next_offset);
+ if (G_UNLIKELY (allocator->config.debug_blocks) &&
+ !smc_notify_free (current, mem_size))
+ abort();
+ if (G_UNLIKELY (g_mem_gc_friendly))
+ memset (current, 0, mem_size);
+ g_free (current);
+ }
+ }
}
/* --- single page allocator --- */
diff --git a/glib/gslice.h b/glib/gslice.h
index 80762761f..3b1a9cbf3 100644
--- a/glib/gslice.h
+++ b/glib/gslice.h
@@ -79,7 +79,8 @@ typedef enum {
G_SLICE_CONFIG_WORKING_SET_MSECS,
G_SLICE_CONFIG_COLOR_INCREMENT,
G_SLICE_CONFIG_CHUNK_SIZES,
- G_SLICE_CONFIG_CONTENTION_COUNTER
+ G_SLICE_CONFIG_CONTENTION_COUNTER,
+ G_SLICE_CONFIG_USE_JEMALLOC
} GSliceConfig;
GLIB_DEPRECATED_IN_2_34