diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2018-05-09 15:44:35 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2018-05-09 15:44:35 +0100 |
commit | 7d0567ac84c97e5357b8997a4c9e4fa7541c917b (patch) | |
tree | 023899e388a790fbd9764a5408a4e799a431fb74 | |
parent | 3d2ab4680dd056e0731220fa387cc79456ae01cc (diff) | |
download | glib-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.ac | 24 | ||||
-rw-r--r-- | glib-2.0.pc.in | 2 | ||||
-rw-r--r-- | glib/Makefile.am | 4 | ||||
-rw-r--r-- | glib/gslice.c | 87 | ||||
-rw-r--r-- | glib/gslice.h | 3 |
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 |