Refactor *decay_time into *decay_ms.

Support millisecond resolution for decay times.  Among other use cases
this makes it possible to specify a short initial dirty-->muzzy decay
phase, followed by a longer muzzy-->clean decay phase.

This resolves #812.
This commit is contained in:
Jason Evans 2017-05-17 10:47:00 -07:00
parent baf3e294e0
commit 6e62c62862
16 changed files with 320 additions and 328 deletions

View File

@ -116,7 +116,7 @@ any of the following arguments (not a definitive list) to 'configure':
MALLOC_CONF environment variable. For example, to change the default decay MALLOC_CONF environment variable. For example, to change the default decay
time to 30 seconds: time to 30 seconds:
--with-malloc-conf=decay_time:30 --with-malloc-conf=decay_ms:30000
* `--enable-debug` * `--enable-debug`

View File

@ -479,8 +479,8 @@ ifeq ($(enable_prof), 1)
$(MALLOC_CONF)="prof:true,prof_active:false" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) $(MALLOC_CONF)="prof:true,prof_active:false" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%)
endif endif
check_integration_decay: tests_integration check_integration_dir check_integration_decay: tests_integration check_integration_dir
$(MALLOC_CONF)="dirty_decay_time:-1,muzzy_decay_time:-1" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) $(MALLOC_CONF)="dirty_decay_ms:-1,muzzy_decay_ms:-1" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%)
$(MALLOC_CONF)="dirty_decay_time:0,muzzy_decay_time:0" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) $(MALLOC_CONF)="dirty_decay_ms:0,muzzy_decay_ms:0" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%)
check_integration: tests_integration check_integration_dir check_integration: tests_integration check_integration_dir
$(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%)
stress: tests_stress stress_dir stress: tests_stress stress_dir

View File

@ -937,15 +937,15 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
<quote>percpu</quote>. </para></listitem> <quote>percpu</quote>. </para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="opt.dirty_decay_time"> <varlistentry id="opt.dirty_decay_ms">
<term> <term>
<mallctl>opt.dirty_decay_time</mallctl> <mallctl>opt.dirty_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>r-</literal> <literal>r-</literal>
</term> </term>
<listitem><para>Approximate time in seconds from the creation of a set <listitem><para>Approximate time in milliseconds from the creation of a
of unused dirty pages until an equivalent set of unused dirty pages is set of unused dirty pages until an equivalent set of unused dirty pages
purged (i.e. converted to muzzy via e.g. is purged (i.e. converted to muzzy via e.g.
<function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function> <function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function>
if supported by the operating system, or converted to clean otherwise) if supported by the operating system, or converted to clean otherwise)
and/or reused. Dirty pages are defined as previously having been and/or reused. Dirty pages are defined as previously having been
@ -955,35 +955,35 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
zero purge rate. A decay time of 0 causes all unused dirty pages to be zero purge rate. A decay time of 0 causes all unused dirty pages to be
purged immediately upon creation. A decay time of -1 disables purging. purged immediately upon creation. A decay time of -1 disables purging.
The default decay time is 10 seconds. See <link The default decay time is 10 seconds. See <link
linkend="arenas.dirty_decay_time"><mallctl>arenas.dirty_decay_time</mallctl></link> linkend="arenas.dirty_decay_ms"><mallctl>arenas.dirty_decay_ms</mallctl></link>
and <link and <link
linkend="arena.i.muzzy_decay_time"><mallctl>arena.&lt;i&gt;.muzzy_decay_time</mallctl></link> linkend="arena.i.muzzy_decay_ms"><mallctl>arena.&lt;i&gt;.muzzy_decay_ms</mallctl></link>
for related dynamic control options. See <link for related dynamic control options. See <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link>
for a description of muzzy pages.</para></listitem> for a description of muzzy pages.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="opt.muzzy_decay_time"> <varlistentry id="opt.muzzy_decay_ms">
<term> <term>
<mallctl>opt.muzzy_decay_time</mallctl> <mallctl>opt.muzzy_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>r-</literal> <literal>r-</literal>
</term> </term>
<listitem><para>Approximate time in seconds from the creation of a set <listitem><para>Approximate time in milliseconds from the creation of a
of unused muzzy pages until an equivalent set of unused muzzy pages is set of unused muzzy pages until an equivalent set of unused muzzy pages
purged (i.e. converted to clean) and/or reused. Muzzy pages are defined is purged (i.e. converted to clean) and/or reused. Muzzy pages are
as previously having been unused dirty pages that were subsequently defined as previously having been unused dirty pages that were
purged in a manner that left them subject to the reclamation whims of subsequently purged in a manner that left them subject to the
the operating system (e.g. reclamation whims of the operating system (e.g.
<function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function>), <function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function>),
and therefore in an indeterminate state. The pages are incrementally and therefore in an indeterminate state. The pages are incrementally
purged according to a sigmoidal decay curve that starts and ends with purged according to a sigmoidal decay curve that starts and ends with
zero purge rate. A decay time of 0 causes all unused muzzy pages to be zero purge rate. A decay time of 0 causes all unused muzzy pages to be
purged immediately upon creation. A decay time of -1 disables purging. purged immediately upon creation. A decay time of -1 disables purging.
The default decay time is 10 seconds. See <link The default decay time is 10 seconds. See <link
linkend="arenas.muzzy_decay_time"><mallctl>arenas.muzzy_decay_time</mallctl></link> linkend="arenas.muzzy_decay_ms"><mallctl>arenas.muzzy_decay_ms</mallctl></link>
and <link and <link
linkend="arena.i.muzzy_decay_time"><mallctl>arena.&lt;i&gt;.muzzy_decay_time</mallctl></link> linkend="arena.i.muzzy_decay_ms"><mallctl>arena.&lt;i&gt;.muzzy_decay_ms</mallctl></link>
for related dynamic control options.</para></listitem> for related dynamic control options.</para></listitem>
</varlistentry> </varlistentry>
@ -1486,9 +1486,9 @@ malloc_conf = "xmalloc:true";]]></programlisting>
for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals for arena &lt;i&gt;, or for all arenas if &lt;i&gt; equals
<constant>MALLCTL_ARENAS_ALL</constant>. The proportion of unused <constant>MALLCTL_ARENAS_ALL</constant>. The proportion of unused
dirty/muzzy pages to be purged depends on the current time; see <link dirty/muzzy pages to be purged depends on the current time; see <link
linkend="opt.dirty_decay_time"><mallctl>opt.dirty_decay_time</mallctl></link> linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link>
and <link and <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzy_decay_ms</mallctl></link>
for details.</para></listitem> for details.</para></listitem>
</varlistentry> </varlistentry>
@ -1550,35 +1550,35 @@ malloc_conf = "xmalloc:true";]]></programlisting>
settings.</para></listitem> settings.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="arena.i.dirty_decay_time"> <varlistentry id="arena.i.dirty_decay_ms">
<term> <term>
<mallctl>arena.&lt;i&gt;.dirty_decay_time</mallctl> <mallctl>arena.&lt;i&gt;.dirty_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>rw</literal> <literal>rw</literal>
</term> </term>
<listitem><para>Current per-arena approximate time in seconds from the <listitem><para>Current per-arena approximate time in milliseconds from
creation of a set of unused dirty pages until an equivalent set of the creation of a set of unused dirty pages until an equivalent set of
unused dirty pages is purged and/or reused. Each time this interface is unused dirty pages is purged and/or reused. Each time this interface is
set, all currently unused dirty pages are considered to have fully set, all currently unused dirty pages are considered to have fully
decayed, which causes immediate purging of all unused dirty pages unless decayed, which causes immediate purging of all unused dirty pages unless
the decay time is set to -1 (i.e. purging disabled). See <link the decay time is set to -1 (i.e. purging disabled). See <link
linkend="opt.dirty_decay_time"><mallctl>opt.dirty_decay_time</mallctl></link> linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link>
for additional information.</para></listitem> for additional information.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="arena.i.muzzy_decay_time"> <varlistentry id="arena.i.muzzy_decay_ms">
<term> <term>
<mallctl>arena.&lt;i&gt;.muzzy_decay_time</mallctl> <mallctl>arena.&lt;i&gt;.muzzy_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>rw</literal> <literal>rw</literal>
</term> </term>
<listitem><para>Current per-arena approximate time in seconds from the <listitem><para>Current per-arena approximate time in milliseconds from
creation of a set of unused muzzy pages until an equivalent set of the creation of a set of unused muzzy pages until an equivalent set of
unused muzzy pages is purged and/or reused. Each time this interface is unused muzzy pages is purged and/or reused. Each time this interface is
set, all currently unused muzzy pages are considered to have fully set, all currently unused muzzy pages are considered to have fully
decayed, which causes immediate purging of all unused muzzy pages unless decayed, which causes immediate purging of all unused muzzy pages unless
the decay time is set to -1 (i.e. purging disabled). See <link the decay time is set to -1 (i.e. purging disabled). See <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link>
for additional information.</para></listitem> for additional information.</para></listitem>
</varlistentry> </varlistentry>
@ -1825,33 +1825,35 @@ struct extent_hooks_s {
<listitem><para>Current limit on number of arenas.</para></listitem> <listitem><para>Current limit on number of arenas.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="arenas.dirty_decay_time"> <varlistentry id="arenas.dirty_decay_ms">
<term> <term>
<mallctl>arenas.dirty_decay_time</mallctl> <mallctl>arenas.dirty_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>rw</literal> <literal>rw</literal>
</term> </term>
<listitem><para>Current default per-arena approximate time in seconds <listitem><para>Current default per-arena approximate time in
from the creation of a set of unused dirty pages until an equivalent set milliseconds from the creation of a set of unused dirty pages until an
of unused dirty pages is purged and/or reused, used to initialize <link equivalent set of unused dirty pages is purged and/or reused, used to
linkend="arena.i.dirty_decay_time"><mallctl>arena.&lt;i&gt;.dirty_decay_time</mallctl></link> initialize <link
linkend="arena.i.dirty_decay_ms"><mallctl>arena.&lt;i&gt;.dirty_decay_ms</mallctl></link>
during arena creation. See <link during arena creation. See <link
linkend="opt.dirty_decay_time"><mallctl>opt.dirty_decay_time</mallctl></link> linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link>
for additional information.</para></listitem> for additional information.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="arenas.muzzy_decay_time"> <varlistentry id="arenas.muzzy_decay_ms">
<term> <term>
<mallctl>arenas.muzzy_decay_time</mallctl> <mallctl>arenas.muzzy_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>rw</literal> <literal>rw</literal>
</term> </term>
<listitem><para>Current default per-arena approximate time in seconds <listitem><para>Current default per-arena approximate time in
from the creation of a set of unused muzzy pages until an equivalent set milliseconds from the creation of a set of unused muzzy pages until an
of unused muzzy pages is purged and/or reused, used to initialize <link equivalent set of unused muzzy pages is purged and/or reused, used to
linkend="arena.i.muzzy_decay_time"><mallctl>arena.&lt;i&gt;.muzzy_decay_time</mallctl></link> initialize <link
linkend="arena.i.muzzy_decay_ms"><mallctl>arena.&lt;i&gt;.muzzy_decay_ms</mallctl></link>
during arena creation. See <link during arena creation. See <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link>
for additional information.</para></listitem> for additional information.</para></listitem>
</varlistentry> </varlistentry>
@ -2244,29 +2246,29 @@ struct extent_hooks_s {
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="stats.arenas.i.dirty_decay_time"> <varlistentry id="stats.arenas.i.dirty_decay_ms">
<term> <term>
<mallctl>stats.arenas.&lt;i&gt;.dirty_decay_time</mallctl> <mallctl>stats.arenas.&lt;i&gt;.dirty_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>r-</literal> <literal>r-</literal>
</term> </term>
<listitem><para>Approximate time in seconds from the creation of a set <listitem><para>Approximate time in milliseconds from the creation of a
of unused dirty pages until an equivalent set of unused dirty pages is set of unused dirty pages until an equivalent set of unused dirty pages
purged and/or reused. See <link is purged and/or reused. See <link
linkend="opt.dirty_decay_time"><mallctl>opt.dirty_decay_time</mallctl></link> linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link>
for details.</para></listitem> for details.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="stats.arenas.i.muzzy_decay_time"> <varlistentry id="stats.arenas.i.muzzy_decay_ms">
<term> <term>
<mallctl>stats.arenas.&lt;i&gt;.muzzy_decay_time</mallctl> <mallctl>stats.arenas.&lt;i&gt;.muzzy_decay_ms</mallctl>
(<type>ssize_t</type>) (<type>ssize_t</type>)
<literal>r-</literal> <literal>r-</literal>
</term> </term>
<listitem><para>Approximate time in seconds from the creation of a set <listitem><para>Approximate time in milliseconds from the creation of a
of unused muzzy pages until an equivalent set of unused muzzy pages is set of unused muzzy pages until an equivalent set of unused muzzy pages
purged and/or reused. See <link is purged and/or reused. See <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link>
for details.</para></listitem> for details.</para></listitem>
</varlistentry> </varlistentry>
@ -2310,7 +2312,7 @@ struct extent_hooks_s {
<listitem><para>Number of pages within unused extents that are <listitem><para>Number of pages within unused extents that are
potentially dirty, and for which <function>madvise()</function> or potentially dirty, and for which <function>madvise()</function> or
similar has not been called. See <link similar has not been called. See <link
linkend="opt.dirty_decay_time"><mallctl>opt.dirty_decay_time</mallctl></link> linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link>
for a description of dirty pages.</para></listitem> for a description of dirty pages.</para></listitem>
</varlistentry> </varlistentry>
@ -2322,7 +2324,7 @@ struct extent_hooks_s {
</term> </term>
<listitem><para>Number of pages within unused extents that are muzzy. <listitem><para>Number of pages within unused extents that are muzzy.
See <link See <link
linkend="opt.muzzy_decay_time"><mallctl>opt.muzzy_decay_time</mallctl></link> linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link>
for a description of muzzy pages.</para></listitem> for a description of muzzy pages.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -13,8 +13,8 @@ static const size_t large_pad =
#endif #endif
; ;
extern ssize_t opt_dirty_decay_time; extern ssize_t opt_dirty_decay_ms;
extern ssize_t opt_muzzy_decay_time; extern ssize_t opt_muzzy_decay_ms;
extern const arena_bin_info_t arena_bin_info[NBINS]; extern const arena_bin_info_t arena_bin_info[NBINS];
@ -27,10 +27,10 @@ void arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats,
void arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, void arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats,
size_t size); size_t size);
void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena,
unsigned *nthreads, const char **dss, ssize_t *dirty_decay_time, unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms,
ssize_t *muzzy_decay_time, size_t *nactive, size_t *ndirty, size_t *nmuzzy); ssize_t *muzzy_decay_ms, size_t *nactive, size_t *ndirty, size_t *nmuzzy);
void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
const char **dss, ssize_t *dirty_decay_time, ssize_t *muzzy_decay_time, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats); malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats);
void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena, void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena,
@ -46,12 +46,10 @@ void arena_extent_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena,
extent_t *extent, size_t oldsize); extent_t *extent, size_t oldsize);
void arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, void arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena,
extent_t *extent, size_t oldsize); extent_t *extent, size_t oldsize);
ssize_t arena_dirty_decay_time_get(arena_t *arena); ssize_t arena_dirty_decay_ms_get(arena_t *arena);
bool arena_dirty_decay_time_set(tsdn_t *tsdn, arena_t *arena, bool arena_dirty_decay_ms_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_ms);
ssize_t decay_time); ssize_t arena_muzzy_decay_ms_get(arena_t *arena);
ssize_t arena_muzzy_decay_time_get(arena_t *arena); bool arena_muzzy_decay_ms_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_ms);
bool arena_muzzy_decay_time_set(tsdn_t *tsdn, arena_t *arena,
ssize_t decay_time);
void arena_decay(tsdn_t *tsdn, arena_t *arena, bool all); void arena_decay(tsdn_t *tsdn, arena_t *arena, bool all);
void arena_reset(tsd_t *tsd, arena_t *arena); void arena_reset(tsd_t *tsd, arena_t *arena);
void arena_destroy(tsd_t *tsd, arena_t *arena); void arena_destroy(tsd_t *tsd, arena_t *arena);
@ -79,10 +77,10 @@ void *arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize,
size_t size, size_t alignment, bool zero, tcache_t *tcache); size_t size, size_t alignment, bool zero, tcache_t *tcache);
dss_prec_t arena_dss_prec_get(arena_t *arena); dss_prec_t arena_dss_prec_get(arena_t *arena);
bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);
ssize_t arena_dirty_decay_time_default_get(void); ssize_t arena_dirty_decay_ms_default_get(void);
bool arena_dirty_decay_time_default_set(ssize_t decay_time); bool arena_dirty_decay_ms_default_set(ssize_t decay_ms);
ssize_t arena_muzzy_decay_time_default_get(void); ssize_t arena_muzzy_decay_ms_default_get(void);
bool arena_muzzy_decay_time_default_set(ssize_t decay_time); bool arena_muzzy_decay_ms_default_set(ssize_t decay_ms);
unsigned arena_nthreads_get(arena_t *arena, bool internal); unsigned arena_nthreads_get(arena_t *arena, bool internal);
void arena_nthreads_inc(arena_t *arena, bool internal); void arena_nthreads_inc(arena_t *arena, bool internal);
void arena_nthreads_dec(arena_t *arena, bool internal); void arena_nthreads_dec(arena_t *arena, bool internal);

View File

@ -56,11 +56,11 @@ struct arena_decay_s {
*/ */
bool purging; bool purging;
/* /*
* Approximate time in seconds from the creation of a set of unused * Approximate time in milliseconds from the creation of a set of unused
* dirty pages until an equivalent set of unused dirty pages is purged * dirty pages until an equivalent set of unused dirty pages is purged
* and/or reused. * and/or reused.
*/ */
atomic_zd_t time; atomic_zd_t time_ms;
/* time / SMOOTHSTEP_NSTEPS. */ /* time / SMOOTHSTEP_NSTEPS. */
nstime_t interval; nstime_t interval;
/* /*

View File

@ -7,9 +7,9 @@
#define LG_SLAB_MAXREGS (LG_PAGE - LG_TINY_MIN) #define LG_SLAB_MAXREGS (LG_PAGE - LG_TINY_MIN)
#define SLAB_MAXREGS (1U << LG_SLAB_MAXREGS) #define SLAB_MAXREGS (1U << LG_SLAB_MAXREGS)
/* Default decay times in seconds. */ /* Default decay times in milliseconds. */
#define DIRTY_DECAY_TIME_DEFAULT 10 #define DIRTY_DECAY_MS_DEFAULT ZD(10 * 1000)
#define MUZZY_DECAY_TIME_DEFAULT 10 #define MUZZY_DECAY_MS_DEFAULT ZD(10 * 1000)
/* Number of event ticks between time checks. */ /* Number of event ticks between time checks. */
#define DECAY_NTICKS_PER_UPDATE 1000 #define DECAY_NTICKS_PER_UPDATE 1000

View File

@ -64,8 +64,8 @@ struct ctl_arena_s {
/* Basic stats, supported even if !config_stats. */ /* Basic stats, supported even if !config_stats. */
unsigned nthreads; unsigned nthreads;
const char *dss; const char *dss;
ssize_t dirty_decay_time; ssize_t dirty_decay_ms;
ssize_t muzzy_decay_time; ssize_t muzzy_decay_ms;
size_t pactive; size_t pactive;
size_t pdirty; size_t pdirty;
size_t pmuzzy; size_t pmuzzy;

View File

@ -41,6 +41,9 @@
#ifndef SIZE_T_MAX #ifndef SIZE_T_MAX
# define SIZE_T_MAX SIZE_MAX # define SIZE_T_MAX SIZE_MAX
#endif #endif
#ifndef SSIZE_MAX
# define SSIZE_MAX ((ssize_t)(SIZE_T_MAX >> 1))
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>

View File

@ -18,11 +18,11 @@ const char *percpu_arena_mode_names[] = {
const char *opt_percpu_arena = OPT_PERCPU_ARENA_DEFAULT; const char *opt_percpu_arena = OPT_PERCPU_ARENA_DEFAULT;
percpu_arena_mode_t percpu_arena_mode = PERCPU_ARENA_MODE_DEFAULT; percpu_arena_mode_t percpu_arena_mode = PERCPU_ARENA_MODE_DEFAULT;
ssize_t opt_dirty_decay_time = DIRTY_DECAY_TIME_DEFAULT; ssize_t opt_dirty_decay_ms = DIRTY_DECAY_MS_DEFAULT;
ssize_t opt_muzzy_decay_time = MUZZY_DECAY_TIME_DEFAULT; ssize_t opt_muzzy_decay_ms = MUZZY_DECAY_MS_DEFAULT;
static atomic_zd_t dirty_decay_time_default; static atomic_zd_t dirty_decay_ms_default;
static atomic_zd_t muzzy_decay_time_default; static atomic_zd_t muzzy_decay_ms_default;
const arena_bin_info_t arena_bin_info[NBINS] = { const arena_bin_info_t arena_bin_info[NBINS] = {
#define BIN_INFO_bin_yes(reg_size, slab_size, nregs) \ #define BIN_INFO_bin_yes(reg_size, slab_size, nregs) \
@ -196,13 +196,12 @@ arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, size_t size) {
void void
arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
const char **dss, ssize_t *dirty_decay_time, ssize_t *muzzy_decay_time, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
size_t *nactive, size_t *ndirty, size_t *nactive, size_t *ndirty, size_t *nmuzzy) {
size_t *nmuzzy) {
*nthreads += arena_nthreads_get(arena, false); *nthreads += arena_nthreads_get(arena, false);
*dss = dss_prec_names[arena_dss_prec_get(arena)]; *dss = dss_prec_names[arena_dss_prec_get(arena)];
*dirty_decay_time = arena_dirty_decay_time_get(arena); *dirty_decay_ms = arena_dirty_decay_ms_get(arena);
*muzzy_decay_time = arena_muzzy_decay_time_get(arena); *muzzy_decay_ms = arena_muzzy_decay_ms_get(arena);
*nactive += atomic_load_zu(&arena->nactive, ATOMIC_RELAXED); *nactive += atomic_load_zu(&arena->nactive, ATOMIC_RELAXED);
*ndirty += extents_npages_get(&arena->extents_dirty); *ndirty += extents_npages_get(&arena->extents_dirty);
*nmuzzy += extents_npages_get(&arena->extents_muzzy); *nmuzzy += extents_npages_get(&arena->extents_muzzy);
@ -210,13 +209,13 @@ arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
void void
arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
const char **dss, ssize_t *dirty_decay_time, ssize_t *muzzy_decay_time, const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms,
size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats,
malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats) { malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats) {
cassert(config_stats); cassert(config_stats);
arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_time, arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms,
muzzy_decay_time, nactive, ndirty, nmuzzy); muzzy_decay_ms, nactive, ndirty, nmuzzy);
size_t base_allocated, base_resident, base_mapped; size_t base_allocated, base_resident, base_mapped;
base_stats_get(tsdn, arena->base, &base_allocated, &base_resident, base_stats_get(tsdn, arena->base, &base_allocated, &base_resident,
@ -359,7 +358,7 @@ arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena,
extents_dalloc(tsdn, arena, r_extent_hooks, &arena->extents_dirty, extents_dalloc(tsdn, arena, r_extent_hooks, &arena->extents_dirty,
extent); extent);
if (arena_dirty_decay_time_get(arena) == 0) { if (arena_dirty_decay_ms_get(arena) == 0) {
arena_decay_dirty(tsdn, arena, true); arena_decay_dirty(tsdn, arena, true);
} }
} }
@ -574,13 +573,13 @@ arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, extent_t *extent,
} }
static ssize_t static ssize_t
arena_decay_time_read(arena_decay_t *decay) { arena_decay_ms_read(arena_decay_t *decay) {
return atomic_load_zd(&decay->time, ATOMIC_RELAXED); return atomic_load_zd(&decay->time_ms, ATOMIC_RELAXED);
} }
static void static void
arena_decay_time_write(arena_decay_t *decay, ssize_t decay_time) { arena_decay_ms_write(arena_decay_t *decay, ssize_t decay_ms) {
atomic_store_zd(&decay->time, decay_time, ATOMIC_RELAXED); atomic_store_zd(&decay->time_ms, decay_ms, ATOMIC_RELAXED);
} }
static void static void
@ -591,7 +590,7 @@ arena_decay_deadline_init(arena_decay_t *decay) {
*/ */
nstime_copy(&decay->deadline, &decay->epoch); nstime_copy(&decay->deadline, &decay->epoch);
nstime_add(&decay->deadline, &decay->interval); nstime_add(&decay->deadline, &decay->interval);
if (arena_decay_time_read(decay) > 0) { if (arena_decay_ms_read(decay) > 0) {
nstime_t jitter; nstime_t jitter;
nstime_init(&jitter, prng_range_u64(&decay->jitter_state, nstime_init(&jitter, prng_range_u64(&decay->jitter_state,
@ -711,11 +710,11 @@ arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
} }
static void static void
arena_decay_reinit(arena_decay_t *decay, extents_t *extents, arena_decay_reinit(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms) {
ssize_t decay_time) { arena_decay_ms_write(decay, decay_ms);
arena_decay_time_write(decay, decay_time); if (decay_ms > 0) {
if (decay_time > 0) { nstime_init(&decay->interval, (uint64_t)decay_ms *
nstime_init2(&decay->interval, decay_time, 0); KQU(1000000));
nstime_idivide(&decay->interval, SMOOTHSTEP_NSTEPS); nstime_idivide(&decay->interval, SMOOTHSTEP_NSTEPS);
} }
@ -728,7 +727,7 @@ arena_decay_reinit(arena_decay_t *decay, extents_t *extents,
} }
static bool static bool
arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_time, arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms,
decay_stats_t *stats) { decay_stats_t *stats) {
if (config_debug) { if (config_debug) {
for (size_t i = 0; i < sizeof(arena_decay_t); i++) { for (size_t i = 0; i < sizeof(arena_decay_t); i++) {
@ -739,7 +738,7 @@ arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_time,
return true; return true;
} }
decay->purging = false; decay->purging = false;
arena_decay_reinit(decay, extents, decay_time); arena_decay_reinit(decay, extents, decay_ms);
/* Memory is zeroed, so there is no need to clear stats. */ /* Memory is zeroed, so there is no need to clear stats. */
if (config_stats) { if (config_stats) {
decay->stats = stats; decay->stats = stats;
@ -748,11 +747,12 @@ arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_time,
} }
static bool static bool
arena_decay_time_valid(ssize_t decay_time) { arena_decay_ms_valid(ssize_t decay_ms) {
if (decay_time < -1) { if (decay_ms < -1) {
return false; return false;
} }
if (decay_time == -1 || (uint64_t)decay_time <= NSTIME_SEC_MAX) { if (decay_ms == -1 || (uint64_t)decay_ms <= NSTIME_SEC_MAX *
KQU(1000)) {
return true; return true;
} }
return false; return false;
@ -764,9 +764,9 @@ arena_maybe_decay(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
malloc_mutex_assert_owner(tsdn, &decay->mtx); malloc_mutex_assert_owner(tsdn, &decay->mtx);
/* Purge all or nothing if the option is disabled. */ /* Purge all or nothing if the option is disabled. */
ssize_t decay_time = arena_decay_time_read(decay); ssize_t decay_ms = arena_decay_ms_read(decay);
if (decay_time <= 0) { if (decay_ms <= 0) {
if (decay_time == 0) { if (decay_ms == 0) {
arena_decay_to_limit(tsdn, arena, decay, extents, false, arena_decay_to_limit(tsdn, arena, decay, extents, false,
0); 0);
} }
@ -806,24 +806,24 @@ arena_maybe_decay(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
} }
static ssize_t static ssize_t
arena_decay_time_get(arena_decay_t *decay) { arena_decay_ms_get(arena_decay_t *decay) {
return arena_decay_time_read(decay); return arena_decay_ms_read(decay);
} }
ssize_t ssize_t
arena_dirty_decay_time_get(arena_t *arena) { arena_dirty_decay_ms_get(arena_t *arena) {
return arena_decay_time_get(&arena->decay_dirty); return arena_decay_ms_get(&arena->decay_dirty);
} }
ssize_t ssize_t
arena_muzzy_decay_time_get(arena_t *arena) { arena_muzzy_decay_ms_get(arena_t *arena) {
return arena_decay_time_get(&arena->decay_muzzy); return arena_decay_ms_get(&arena->decay_muzzy);
} }
static bool static bool
arena_decay_time_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, arena_decay_ms_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
extents_t *extents, ssize_t decay_time) { extents_t *extents, ssize_t decay_ms) {
if (!arena_decay_time_valid(decay_time)) { if (!arena_decay_ms_valid(decay_ms)) {
return true; return true;
} }
@ -832,11 +832,11 @@ arena_decay_time_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
* Restart decay backlog from scratch, which may cause many dirty pages * Restart decay backlog from scratch, which may cause many dirty pages
* to be immediately purged. It would conceptually be possible to map * to be immediately purged. It would conceptually be possible to map
* the old backlog onto the new backlog, but there is no justification * the old backlog onto the new backlog, but there is no justification
* for such complexity since decay_time changes are intended to be * for such complexity since decay_ms changes are intended to be
* infrequent, either between the {-1, 0, >0} states, or a one-time * infrequent, either between the {-1, 0, >0} states, or a one-time
* arbitrary change during initial arena configuration. * arbitrary change during initial arena configuration.
*/ */
arena_decay_reinit(decay, extents, decay_time); arena_decay_reinit(decay, extents, decay_ms);
arena_maybe_decay(tsdn, arena, decay, extents); arena_maybe_decay(tsdn, arena, decay, extents);
malloc_mutex_unlock(tsdn, &decay->mtx); malloc_mutex_unlock(tsdn, &decay->mtx);
@ -844,15 +844,17 @@ arena_decay_time_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay,
} }
bool bool
arena_dirty_decay_time_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_time) { arena_dirty_decay_ms_set(tsdn_t *tsdn, arena_t *arena,
return arena_decay_time_set(tsdn, arena, &arena->decay_dirty, ssize_t decay_ms) {
&arena->extents_dirty, decay_time); return arena_decay_ms_set(tsdn, arena, &arena->decay_dirty,
&arena->extents_dirty, decay_ms);
} }
bool bool
arena_muzzy_decay_time_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_time) { arena_muzzy_decay_ms_set(tsdn_t *tsdn, arena_t *arena,
return arena_decay_time_set(tsdn, arena, &arena->decay_muzzy, ssize_t decay_ms) {
&arena->extents_muzzy, decay_time); return arena_decay_ms_set(tsdn, arena, &arena->decay_muzzy,
&arena->extents_muzzy, decay_ms);
} }
static size_t static size_t
@ -885,7 +887,7 @@ arena_decay_stashed(tsdn_t *tsdn, arena_t *arena,
} }
npurged = 0; npurged = 0;
ssize_t muzzy_decay_time = arena_muzzy_decay_time_get(arena); ssize_t muzzy_decay_ms = arena_muzzy_decay_ms_get(arena);
for (extent_t *extent = extent_list_first(decay_extents); extent != for (extent_t *extent = extent_list_first(decay_extents); extent !=
NULL; extent = extent_list_first(decay_extents)) { NULL; extent = extent_list_first(decay_extents)) {
if (config_stats) { if (config_stats) {
@ -898,7 +900,7 @@ arena_decay_stashed(tsdn_t *tsdn, arena_t *arena,
case extent_state_active: case extent_state_active:
not_reached(); not_reached();
case extent_state_dirty: case extent_state_dirty:
if (!all && muzzy_decay_time != 0 && if (!all && muzzy_decay_ms != 0 &&
!extent_purge_lazy_wrapper(tsdn, arena, !extent_purge_lazy_wrapper(tsdn, arena,
r_extent_hooks, extent, 0, r_extent_hooks, extent, 0,
extent_size_get(extent))) { extent_size_get(extent))) {
@ -1789,30 +1791,30 @@ arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) {
} }
ssize_t ssize_t
arena_dirty_decay_time_default_get(void) { arena_dirty_decay_ms_default_get(void) {
return atomic_load_zd(&dirty_decay_time_default, ATOMIC_RELAXED); return atomic_load_zd(&dirty_decay_ms_default, ATOMIC_RELAXED);
} }
bool bool
arena_dirty_decay_time_default_set(ssize_t decay_time) { arena_dirty_decay_ms_default_set(ssize_t decay_ms) {
if (!arena_decay_time_valid(decay_time)) { if (!arena_decay_ms_valid(decay_ms)) {
return true; return true;
} }
atomic_store_zd(&dirty_decay_time_default, decay_time, ATOMIC_RELAXED); atomic_store_zd(&dirty_decay_ms_default, decay_ms, ATOMIC_RELAXED);
return false; return false;
} }
ssize_t ssize_t
arena_muzzy_decay_time_default_get(void) { arena_muzzy_decay_ms_default_get(void) {
return atomic_load_zd(&muzzy_decay_time_default, ATOMIC_RELAXED); return atomic_load_zd(&muzzy_decay_ms_default, ATOMIC_RELAXED);
} }
bool bool
arena_muzzy_decay_time_default_set(ssize_t decay_time) { arena_muzzy_decay_ms_default_set(ssize_t decay_ms) {
if (!arena_decay_time_valid(decay_time)) { if (!arena_decay_ms_valid(decay_ms)) {
return true; return true;
} }
atomic_store_zd(&muzzy_decay_time_default, decay_time, ATOMIC_RELAXED); atomic_store_zd(&muzzy_decay_ms_default, decay_ms, ATOMIC_RELAXED);
return false; return false;
} }
@ -1933,11 +1935,11 @@ arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
} }
if (arena_decay_init(&arena->decay_dirty, &arena->extents_dirty, if (arena_decay_init(&arena->decay_dirty, &arena->extents_dirty,
arena_dirty_decay_time_default_get(), &arena->stats.decay_dirty)) { arena_dirty_decay_ms_default_get(), &arena->stats.decay_dirty)) {
goto label_error; goto label_error;
} }
if (arena_decay_init(&arena->decay_muzzy, &arena->extents_muzzy, if (arena_decay_init(&arena->decay_muzzy, &arena->extents_muzzy,
arena_muzzy_decay_time_default_get(), &arena->stats.decay_muzzy)) { arena_muzzy_decay_ms_default_get(), &arena->stats.decay_muzzy)) {
goto label_error; goto label_error;
} }
@ -1993,8 +1995,8 @@ label_error:
void void
arena_boot(void) { arena_boot(void) {
arena_dirty_decay_time_default_set(opt_dirty_decay_time); arena_dirty_decay_ms_default_set(opt_dirty_decay_ms);
arena_muzzy_decay_time_default_set(opt_muzzy_decay_time); arena_muzzy_decay_ms_default_set(opt_muzzy_decay_ms);
} }
void void

View File

@ -78,8 +78,8 @@ CTL_PROTO(opt_retain)
CTL_PROTO(opt_dss) CTL_PROTO(opt_dss)
CTL_PROTO(opt_narenas) CTL_PROTO(opt_narenas)
CTL_PROTO(opt_percpu_arena) CTL_PROTO(opt_percpu_arena)
CTL_PROTO(opt_dirty_decay_time) CTL_PROTO(opt_dirty_decay_ms)
CTL_PROTO(opt_muzzy_decay_time) CTL_PROTO(opt_muzzy_decay_ms)
CTL_PROTO(opt_stats_print) CTL_PROTO(opt_stats_print)
CTL_PROTO(opt_junk) CTL_PROTO(opt_junk)
CTL_PROTO(opt_zero) CTL_PROTO(opt_zero)
@ -106,8 +106,8 @@ CTL_PROTO(arena_i_purge)
CTL_PROTO(arena_i_reset) CTL_PROTO(arena_i_reset)
CTL_PROTO(arena_i_destroy) CTL_PROTO(arena_i_destroy)
CTL_PROTO(arena_i_dss) CTL_PROTO(arena_i_dss)
CTL_PROTO(arena_i_dirty_decay_time) CTL_PROTO(arena_i_dirty_decay_ms)
CTL_PROTO(arena_i_muzzy_decay_time) CTL_PROTO(arena_i_muzzy_decay_ms)
CTL_PROTO(arena_i_extent_hooks) CTL_PROTO(arena_i_extent_hooks)
INDEX_PROTO(arena_i) INDEX_PROTO(arena_i)
CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_size)
@ -117,8 +117,8 @@ INDEX_PROTO(arenas_bin_i)
CTL_PROTO(arenas_lextent_i_size) CTL_PROTO(arenas_lextent_i_size)
INDEX_PROTO(arenas_lextent_i) INDEX_PROTO(arenas_lextent_i)
CTL_PROTO(arenas_narenas) CTL_PROTO(arenas_narenas)
CTL_PROTO(arenas_dirty_decay_time) CTL_PROTO(arenas_dirty_decay_ms)
CTL_PROTO(arenas_muzzy_decay_time) CTL_PROTO(arenas_muzzy_decay_ms)
CTL_PROTO(arenas_quantum) CTL_PROTO(arenas_quantum)
CTL_PROTO(arenas_page) CTL_PROTO(arenas_page)
CTL_PROTO(arenas_tcache_max) CTL_PROTO(arenas_tcache_max)
@ -159,8 +159,8 @@ INDEX_PROTO(stats_arenas_i_lextents_j)
CTL_PROTO(stats_arenas_i_nthreads) CTL_PROTO(stats_arenas_i_nthreads)
CTL_PROTO(stats_arenas_i_uptime) CTL_PROTO(stats_arenas_i_uptime)
CTL_PROTO(stats_arenas_i_dss) CTL_PROTO(stats_arenas_i_dss)
CTL_PROTO(stats_arenas_i_dirty_decay_time) CTL_PROTO(stats_arenas_i_dirty_decay_ms)
CTL_PROTO(stats_arenas_i_muzzy_decay_time) CTL_PROTO(stats_arenas_i_muzzy_decay_ms)
CTL_PROTO(stats_arenas_i_pactive) CTL_PROTO(stats_arenas_i_pactive)
CTL_PROTO(stats_arenas_i_pdirty) CTL_PROTO(stats_arenas_i_pdirty)
CTL_PROTO(stats_arenas_i_pmuzzy) CTL_PROTO(stats_arenas_i_pmuzzy)
@ -265,8 +265,8 @@ static const ctl_named_node_t opt_node[] = {
{NAME("dss"), CTL(opt_dss)}, {NAME("dss"), CTL(opt_dss)},
{NAME("narenas"), CTL(opt_narenas)}, {NAME("narenas"), CTL(opt_narenas)},
{NAME("percpu_arena"), CTL(opt_percpu_arena)}, {NAME("percpu_arena"), CTL(opt_percpu_arena)},
{NAME("dirty_decay_time"), CTL(opt_dirty_decay_time)}, {NAME("dirty_decay_ms"), CTL(opt_dirty_decay_ms)},
{NAME("muzzy_decay_time"), CTL(opt_muzzy_decay_time)}, {NAME("muzzy_decay_ms"), CTL(opt_muzzy_decay_ms)},
{NAME("stats_print"), CTL(opt_stats_print)}, {NAME("stats_print"), CTL(opt_stats_print)},
{NAME("junk"), CTL(opt_junk)}, {NAME("junk"), CTL(opt_junk)},
{NAME("zero"), CTL(opt_zero)}, {NAME("zero"), CTL(opt_zero)},
@ -299,8 +299,8 @@ static const ctl_named_node_t arena_i_node[] = {
{NAME("reset"), CTL(arena_i_reset)}, {NAME("reset"), CTL(arena_i_reset)},
{NAME("destroy"), CTL(arena_i_destroy)}, {NAME("destroy"), CTL(arena_i_destroy)},
{NAME("dss"), CTL(arena_i_dss)}, {NAME("dss"), CTL(arena_i_dss)},
{NAME("dirty_decay_time"), CTL(arena_i_dirty_decay_time)}, {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)},
{NAME("muzzy_decay_time"), CTL(arena_i_muzzy_decay_time)}, {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)},
{NAME("extent_hooks"), CTL(arena_i_extent_hooks)} {NAME("extent_hooks"), CTL(arena_i_extent_hooks)}
}; };
static const ctl_named_node_t super_arena_i_node[] = { static const ctl_named_node_t super_arena_i_node[] = {
@ -337,8 +337,8 @@ static const ctl_indexed_node_t arenas_lextent_node[] = {
static const ctl_named_node_t arenas_node[] = { static const ctl_named_node_t arenas_node[] = {
{NAME("narenas"), CTL(arenas_narenas)}, {NAME("narenas"), CTL(arenas_narenas)},
{NAME("dirty_decay_time"), CTL(arenas_dirty_decay_time)}, {NAME("dirty_decay_ms"), CTL(arenas_dirty_decay_ms)},
{NAME("muzzy_decay_time"), CTL(arenas_muzzy_decay_time)}, {NAME("muzzy_decay_ms"), CTL(arenas_muzzy_decay_ms)},
{NAME("quantum"), CTL(arenas_quantum)}, {NAME("quantum"), CTL(arenas_quantum)},
{NAME("page"), CTL(arenas_page)}, {NAME("page"), CTL(arenas_page)},
{NAME("tcache_max"), CTL(arenas_tcache_max)}, {NAME("tcache_max"), CTL(arenas_tcache_max)},
@ -444,8 +444,8 @@ static const ctl_named_node_t stats_arenas_i_node[] = {
{NAME("nthreads"), CTL(stats_arenas_i_nthreads)}, {NAME("nthreads"), CTL(stats_arenas_i_nthreads)},
{NAME("uptime"), CTL(stats_arenas_i_uptime)}, {NAME("uptime"), CTL(stats_arenas_i_uptime)},
{NAME("dss"), CTL(stats_arenas_i_dss)}, {NAME("dss"), CTL(stats_arenas_i_dss)},
{NAME("dirty_decay_time"), CTL(stats_arenas_i_dirty_decay_time)}, {NAME("dirty_decay_ms"), CTL(stats_arenas_i_dirty_decay_ms)},
{NAME("muzzy_decay_time"), CTL(stats_arenas_i_muzzy_decay_time)}, {NAME("muzzy_decay_ms"), CTL(stats_arenas_i_muzzy_decay_ms)},
{NAME("pactive"), CTL(stats_arenas_i_pactive)}, {NAME("pactive"), CTL(stats_arenas_i_pactive)},
{NAME("pdirty"), CTL(stats_arenas_i_pdirty)}, {NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
{NAME("pmuzzy"), CTL(stats_arenas_i_pmuzzy)}, {NAME("pmuzzy"), CTL(stats_arenas_i_pmuzzy)},
@ -644,8 +644,8 @@ static void
ctl_arena_clear(ctl_arena_t *ctl_arena) { ctl_arena_clear(ctl_arena_t *ctl_arena) {
ctl_arena->nthreads = 0; ctl_arena->nthreads = 0;
ctl_arena->dss = dss_prec_names[dss_prec_limit]; ctl_arena->dss = dss_prec_names[dss_prec_limit];
ctl_arena->dirty_decay_time = -1; ctl_arena->dirty_decay_ms = -1;
ctl_arena->muzzy_decay_time = -1; ctl_arena->muzzy_decay_ms = -1;
ctl_arena->pactive = 0; ctl_arena->pactive = 0;
ctl_arena->pdirty = 0; ctl_arena->pdirty = 0;
ctl_arena->pmuzzy = 0; ctl_arena->pmuzzy = 0;
@ -668,8 +668,8 @@ ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) {
if (config_stats) { if (config_stats) {
arena_stats_merge(tsdn, arena, &ctl_arena->nthreads, arena_stats_merge(tsdn, arena, &ctl_arena->nthreads,
&ctl_arena->dss, &ctl_arena->dirty_decay_time, &ctl_arena->dss, &ctl_arena->dirty_decay_ms,
&ctl_arena->muzzy_decay_time, &ctl_arena->pactive, &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
&ctl_arena->pdirty, &ctl_arena->pmuzzy, &ctl_arena->pdirty, &ctl_arena->pmuzzy,
&ctl_arena->astats->astats, ctl_arena->astats->bstats, &ctl_arena->astats->astats, ctl_arena->astats->bstats,
ctl_arena->astats->lstats); ctl_arena->astats->lstats);
@ -687,8 +687,8 @@ ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) {
} }
} else { } else {
arena_basic_stats_merge(tsdn, arena, &ctl_arena->nthreads, arena_basic_stats_merge(tsdn, arena, &ctl_arena->nthreads,
&ctl_arena->dss, &ctl_arena->dirty_decay_time, &ctl_arena->dss, &ctl_arena->dirty_decay_ms,
&ctl_arena->muzzy_decay_time, &ctl_arena->pactive, &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
&ctl_arena->pdirty, &ctl_arena->pmuzzy); &ctl_arena->pdirty, &ctl_arena->pmuzzy);
} }
} }
@ -1465,8 +1465,8 @@ CTL_RO_NL_GEN(opt_retain, opt_retain, bool)
CTL_RO_NL_GEN(opt_dss, opt_dss, const char *) CTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned) CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
CTL_RO_NL_GEN(opt_percpu_arena, opt_percpu_arena, const char *) CTL_RO_NL_GEN(opt_percpu_arena, opt_percpu_arena, const char *)
CTL_RO_NL_GEN(opt_dirty_decay_time, opt_dirty_decay_time, ssize_t) CTL_RO_NL_GEN(opt_dirty_decay_ms, opt_dirty_decay_ms, ssize_t)
CTL_RO_NL_GEN(opt_muzzy_decay_time, opt_muzzy_decay_time, ssize_t) CTL_RO_NL_GEN(opt_muzzy_decay_ms, opt_muzzy_decay_ms, ssize_t)
CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool) CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *) CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
@ -1955,7 +1955,7 @@ label_return:
} }
static int static int
arena_i_decay_time_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, arena_i_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) { void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) {
int ret; int ret;
unsigned arena_ind; unsigned arena_ind;
@ -1969,8 +1969,8 @@ arena_i_decay_time_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
} }
if (oldp != NULL && oldlenp != NULL) { if (oldp != NULL && oldlenp != NULL) {
size_t oldval = dirty ? arena_dirty_decay_time_get(arena) : size_t oldval = dirty ? arena_dirty_decay_ms_get(arena) :
arena_muzzy_decay_time_get(arena); arena_muzzy_decay_ms_get(arena);
READ(oldval, ssize_t); READ(oldval, ssize_t);
} }
if (newp != NULL) { if (newp != NULL) {
@ -1978,10 +1978,9 @@ arena_i_decay_time_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
ret = EINVAL; ret = EINVAL;
goto label_return; goto label_return;
} }
if (dirty ? arena_dirty_decay_time_set(tsd_tsdn(tsd), arena, if (dirty ? arena_dirty_decay_ms_set(tsd_tsdn(tsd), arena,
*(ssize_t *)newp) : *(ssize_t *)newp) : arena_muzzy_decay_ms_set(tsd_tsdn(tsd),
arena_muzzy_decay_time_set(tsd_tsdn(tsd), arena, arena, *(ssize_t *)newp)) {
*(ssize_t *)newp)) {
ret = EFAULT; ret = EFAULT;
goto label_return; goto label_return;
} }
@ -1993,17 +1992,17 @@ label_return:
} }
static int static int
arena_i_dirty_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, arena_i_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
return arena_i_decay_time_ctl_impl(tsd, mib, miblen, oldp, oldlenp, return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
newp, newlen, true); newlen, true);
} }
static int static int
arena_i_muzzy_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, arena_i_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
return arena_i_decay_time_ctl_impl(tsd, mib, miblen, oldp, oldlenp, return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
newp, newlen, false); newlen, false);
} }
static int static int
@ -2087,13 +2086,13 @@ label_return:
} }
static int static int
arenas_decay_time_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) { void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) {
int ret; int ret;
if (oldp != NULL && oldlenp != NULL) { if (oldp != NULL && oldlenp != NULL) {
size_t oldval = (dirty ? arena_dirty_decay_time_default_get() : size_t oldval = (dirty ? arena_dirty_decay_ms_default_get() :
arena_muzzy_decay_time_default_get()); arena_muzzy_decay_ms_default_get());
READ(oldval, ssize_t); READ(oldval, ssize_t);
} }
if (newp != NULL) { if (newp != NULL) {
@ -2101,8 +2100,8 @@ arenas_decay_time_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
ret = EINVAL; ret = EINVAL;
goto label_return; goto label_return;
} }
if (dirty ? arena_dirty_decay_time_default_set(*(ssize_t *)newp) if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp)
: arena_muzzy_decay_time_default_set(*(ssize_t *)newp)) { : arena_muzzy_decay_ms_default_set(*(ssize_t *)newp)) {
ret = EFAULT; ret = EFAULT;
goto label_return; goto label_return;
} }
@ -2114,16 +2113,16 @@ label_return:
} }
static int static int
arenas_dirty_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, arenas_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
return arenas_decay_time_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
newlen, true); newlen, true);
} }
static int static int
arenas_muzzy_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, arenas_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
return arenas_decay_time_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
newlen, false); newlen, false);
} }
@ -2318,9 +2317,9 @@ CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats->mapped, size_t)
CTL_RO_CGEN(config_stats, stats_retained, ctl_stats->retained, size_t) CTL_RO_CGEN(config_stats, stats_retained, ctl_stats->retained, size_t)
CTL_RO_GEN(stats_arenas_i_dss, arenas_i(mib[2])->dss, const char *) CTL_RO_GEN(stats_arenas_i_dss, arenas_i(mib[2])->dss, const char *)
CTL_RO_GEN(stats_arenas_i_dirty_decay_time, arenas_i(mib[2])->dirty_decay_time, CTL_RO_GEN(stats_arenas_i_dirty_decay_ms, arenas_i(mib[2])->dirty_decay_ms,
ssize_t) ssize_t)
CTL_RO_GEN(stats_arenas_i_muzzy_decay_time, arenas_i(mib[2])->muzzy_decay_time, CTL_RO_GEN(stats_arenas_i_muzzy_decay_ms, arenas_i(mib[2])->muzzy_decay_ms,
ssize_t) ssize_t)
CTL_RO_GEN(stats_arenas_i_nthreads, arenas_i(mib[2])->nthreads, unsigned) CTL_RO_GEN(stats_arenas_i_nthreads, arenas_i(mib[2])->nthreads, unsigned)
CTL_RO_GEN(stats_arenas_i_uptime, CTL_RO_GEN(stats_arenas_i_uptime,

View File

@ -1070,10 +1070,14 @@ malloc_conf_init(void) {
} }
CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1, CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
UINT_MAX, yes, no, false) UINT_MAX, yes, no, false)
CONF_HANDLE_SSIZE_T(opt_dirty_decay_time, CONF_HANDLE_SSIZE_T(opt_dirty_decay_ms,
"dirty_decay_time", -1, NSTIME_SEC_MAX); "dirty_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) <
CONF_HANDLE_SSIZE_T(opt_muzzy_decay_time, QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) :
"muzzy_decay_time", -1, NSTIME_SEC_MAX); SSIZE_MAX);
CONF_HANDLE_SSIZE_T(opt_muzzy_decay_ms,
"muzzy_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) <
QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) :
SSIZE_MAX);
CONF_HANDLE_BOOL(opt_stats_print, "stats_print") CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
if (config_fill) { if (config_fill) {
if (CONF_MATCH("junk")) { if (CONF_MATCH("junk")) {

View File

@ -411,7 +411,7 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
bool json, unsigned i, bool bins, bool large, bool mutex) { bool json, unsigned i, bool bins, bool large, bool mutex) {
unsigned nthreads; unsigned nthreads;
const char *dss; const char *dss;
ssize_t dirty_decay_time, muzzy_decay_time; ssize_t dirty_decay_ms, muzzy_decay_ms;
size_t page, pactive, pdirty, pmuzzy, mapped, retained; size_t page, pactive, pdirty, pmuzzy, mapped, retained;
size_t base, internal, resident; size_t base, internal, resident;
uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; uint64_t dirty_npurge, dirty_nmadvise, dirty_purged;
@ -452,9 +452,9 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
"dss allocation precedence: %s\n", dss); "dss allocation precedence: %s\n", dss);
} }
CTL_M2_GET("stats.arenas.0.dirty_decay_time", i, &dirty_decay_time, CTL_M2_GET("stats.arenas.0.dirty_decay_ms", i, &dirty_decay_ms,
ssize_t); ssize_t);
CTL_M2_GET("stats.arenas.0.muzzy_decay_time", i, &muzzy_decay_time, CTL_M2_GET("stats.arenas.0.muzzy_decay_ms", i, &muzzy_decay_ms,
ssize_t); ssize_t);
CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t); CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t);
CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t); CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t);
@ -469,9 +469,9 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
CTL_M2_GET("stats.arenas.0.muzzy_purged", i, &muzzy_purged, uint64_t); CTL_M2_GET("stats.arenas.0.muzzy_purged", i, &muzzy_purged, uint64_t);
if (json) { if (json) {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"\t\t\t\t\"dirty_decay_time\": %zd,\n", dirty_decay_time); "\t\t\t\t\"dirty_decay_ms\": %zd,\n", dirty_decay_ms);
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"\t\t\t\t\"muzzy_decay_time\": %zd,\n", muzzy_decay_time); "\t\t\t\t\"muzzy_decay_ms\": %zd,\n", muzzy_decay_ms);
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"\t\t\t\t\"pactive\": %zu,\n", pactive); "\t\t\t\t\"pactive\": %zu,\n", pactive);
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
@ -494,10 +494,10 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"decaying: time npages sweeps madvises" "decaying: time npages sweeps madvises"
" purged\n"); " purged\n");
if (dirty_decay_time >= 0) { if (dirty_decay_ms >= 0) {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
" dirty: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" " dirty: %5zd %12zu %12"FMTu64" %12"FMTu64" %12"
FMTu64"\n", dirty_decay_time, pdirty, dirty_npurge, FMTu64"\n", dirty_decay_ms, pdirty, dirty_npurge,
dirty_nmadvise, dirty_purged); dirty_nmadvise, dirty_purged);
} else { } else {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
@ -505,10 +505,10 @@ stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
FMTu64"\n", pdirty, dirty_npurge, dirty_nmadvise, FMTu64"\n", pdirty, dirty_npurge, dirty_nmadvise,
dirty_purged); dirty_purged);
} }
if (muzzy_decay_time >= 0) { if (muzzy_decay_ms >= 0) {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
" muzzy: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" " muzzy: %5zd %12zu %12"FMTu64" %12"FMTu64" %12"
FMTu64"\n", muzzy_decay_time, pmuzzy, muzzy_npurge, FMTu64"\n", muzzy_decay_ms, pmuzzy, muzzy_npurge,
muzzy_nmadvise, muzzy_purged); muzzy_nmadvise, muzzy_purged);
} else { } else {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
@ -816,10 +816,8 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
OPT_WRITE_CHAR_P(dss, ",") OPT_WRITE_CHAR_P(dss, ",")
OPT_WRITE_UNSIGNED(narenas, ",") OPT_WRITE_UNSIGNED(narenas, ",")
OPT_WRITE_CHAR_P(percpu_arena, ",") OPT_WRITE_CHAR_P(percpu_arena, ",")
OPT_WRITE_SSIZE_T_MUTABLE(dirty_decay_time, arenas.dirty_decay_time, OPT_WRITE_SSIZE_T_MUTABLE(dirty_decay_ms, arenas.dirty_decay_ms, ",")
",") OPT_WRITE_SSIZE_T_MUTABLE(muzzy_decay_ms, arenas.muzzy_decay_ms, ",")
OPT_WRITE_SSIZE_T_MUTABLE(muzzy_decay_time, arenas.muzzy_decay_time,
",")
OPT_WRITE_CHAR_P(junk, ",") OPT_WRITE_CHAR_P(junk, ",")
OPT_WRITE_BOOL(zero, ",") OPT_WRITE_BOOL(zero, ",")
OPT_WRITE_BOOL(utrace, ",") OPT_WRITE_BOOL(utrace, ",")
@ -867,24 +865,14 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv);
} }
CTL_GET("arenas.dirty_decay_time", &ssv, ssize_t);
if (json) { if (json) {
CTL_GET("arenas.dirty_decay_ms", &ssv, ssize_t);
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"\t\t\t\"dirty_decay_time\": %zd,\n", ssv); "\t\t\t\"dirty_decay_ms\": %zd,\n", ssv);
} else {
malloc_cprintf(write_cb, cbopaque,
"Unused dirty page decay time: %zd%s\n", ssv, (ssv < 0) ?
" (no decay)" : "");
}
CTL_GET("arenas.muzzy_decay_time", &ssv, ssize_t); CTL_GET("arenas.muzzy_decay_ms", &ssv, ssize_t);
if (json) {
malloc_cprintf(write_cb, cbopaque, malloc_cprintf(write_cb, cbopaque,
"\t\t\t\"muzzy_decay_time\": %zd,\n", ssv); "\t\t\t\"muzzy_decay_ms\": %zd,\n", ssv);
} else {
malloc_cprintf(write_cb, cbopaque,
"Unused muzzy page decay time: %zd%s\n", ssv, (ssv < 0) ?
" (no decay)" : "");
} }
CTL_GET("arenas.quantum", &sv, size_t); CTL_GET("arenas.quantum", &sv, size_t);

View File

@ -24,7 +24,7 @@ nstime_update_mock(nstime_t *time) {
} }
static unsigned static unsigned
do_arena_create(ssize_t dirty_decay_time, ssize_t muzzy_decay_time) { do_arena_create(ssize_t dirty_decay_ms, ssize_t muzzy_decay_ms) {
unsigned arena_ind; unsigned arena_ind;
size_t sz = sizeof(unsigned); size_t sz = sizeof(unsigned);
assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0), assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0),
@ -32,19 +32,19 @@ do_arena_create(ssize_t dirty_decay_time, ssize_t muzzy_decay_time) {
size_t mib[3]; size_t mib[3];
size_t miblen = sizeof(mib)/sizeof(size_t); size_t miblen = sizeof(mib)/sizeof(size_t);
assert_d_eq(mallctlnametomib("arena.0.dirty_decay_time", mib, &miblen), assert_d_eq(mallctlnametomib("arena.0.dirty_decay_ms", mib, &miblen),
0, "Unexpected mallctlnametomib() failure"); 0, "Unexpected mallctlnametomib() failure");
mib[1] = (size_t)arena_ind; mib[1] = (size_t)arena_ind;
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL,
(void *)&dirty_decay_time, (void *)&dirty_decay_ms, sizeof(dirty_decay_ms)), 0,
sizeof(dirty_decay_time)), 0, "Unexpected mallctlbymib() failure"); "Unexpected mallctlbymib() failure");
assert_d_eq(mallctlnametomib("arena.0.muzzy_decay_time", mib, &miblen), assert_d_eq(mallctlnametomib("arena.0.muzzy_decay_ms", mib, &miblen),
0, "Unexpected mallctlnametomib() failure"); 0, "Unexpected mallctlnametomib() failure");
mib[1] = (size_t)arena_ind; mib[1] = (size_t)arena_ind;
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL,
(void *)&muzzy_decay_time, (void *)&muzzy_decay_ms, sizeof(muzzy_decay_ms)), 0,
sizeof(muzzy_decay_time)), 0, "Unexpected mallctlbymib() failure"); "Unexpected mallctlbymib() failure");
return arena_ind; return arena_ind;
} }
@ -362,14 +362,14 @@ static void
decay_ticker_helper(unsigned arena_ind, int flags, bool dirty, ssize_t dt, decay_ticker_helper(unsigned arena_ind, int flags, bool dirty, ssize_t dt,
uint64_t dirty_npurge0, uint64_t muzzy_npurge0, bool terminate_asap) { uint64_t dirty_npurge0, uint64_t muzzy_npurge0, bool terminate_asap) {
#define NINTERVALS 101 #define NINTERVALS 101
nstime_t time, update_interval, decay_time, deadline; nstime_t time, update_interval, decay_ms, deadline;
nstime_init(&time, 0); nstime_init(&time, 0);
nstime_update(&time); nstime_update(&time);
nstime_init2(&decay_time, dt, 0); nstime_init2(&decay_ms, dt, 0);
nstime_copy(&deadline, &time); nstime_copy(&deadline, &time);
nstime_add(&deadline, &decay_time); nstime_add(&deadline, &decay_ms);
nstime_init2(&update_interval, dt, 0); nstime_init2(&update_interval, dt, 0);
nstime_idivide(&update_interval, NINTERVALS); nstime_idivide(&update_interval, NINTERVALS);
@ -406,8 +406,8 @@ decay_ticker_helper(unsigned arena_ind, int flags, bool dirty, ssize_t dt,
TEST_BEGIN(test_decay_ticker) { TEST_BEGIN(test_decay_ticker) {
#define NPS 2048 #define NPS 2048
ssize_t ddt = opt_dirty_decay_time; ssize_t ddt = opt_dirty_decay_ms;
ssize_t mdt = opt_muzzy_decay_time; ssize_t mdt = opt_muzzy_decay_ms;
unsigned arena_ind = do_arena_create(ddt, mdt); unsigned arena_ind = do_arena_create(ddt, mdt);
int flags = (MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE); int flags = (MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE);
void *ps[NPS]; void *ps[NPS];

View File

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
export MALLOC_CONF="dirty_decay_time:1,muzzy_decay_time:1,lg_tcache_max:0" export MALLOC_CONF="dirty_decay_ms:1000,muzzy_decay_ms:1000,lg_tcache_max:0"

View File

@ -161,8 +161,8 @@ TEST_BEGIN(test_mallctl_opt) {
TEST_MALLCTL_OPT(const char *, dss, always); TEST_MALLCTL_OPT(const char *, dss, always);
TEST_MALLCTL_OPT(unsigned, narenas, always); TEST_MALLCTL_OPT(unsigned, narenas, always);
TEST_MALLCTL_OPT(const char *, percpu_arena, always); TEST_MALLCTL_OPT(const char *, percpu_arena, always);
TEST_MALLCTL_OPT(ssize_t, dirty_decay_time, always); TEST_MALLCTL_OPT(ssize_t, dirty_decay_ms, always);
TEST_MALLCTL_OPT(ssize_t, muzzy_decay_time, always); TEST_MALLCTL_OPT(ssize_t, muzzy_decay_ms, always);
TEST_MALLCTL_OPT(bool, stats_print, always); TEST_MALLCTL_OPT(bool, stats_print, always);
TEST_MALLCTL_OPT(const char *, junk, fill); TEST_MALLCTL_OPT(const char *, junk, fill);
TEST_MALLCTL_OPT(bool, zero, fill); TEST_MALLCTL_OPT(bool, zero, fill);
@ -398,68 +398,66 @@ TEST_BEGIN(test_arena_i_initialized) {
} }
TEST_END TEST_END
TEST_BEGIN(test_arena_i_dirty_decay_time) { TEST_BEGIN(test_arena_i_dirty_decay_ms) {
ssize_t dirty_decay_time, orig_dirty_decay_time, prev_dirty_decay_time; ssize_t dirty_decay_ms, orig_dirty_decay_ms, prev_dirty_decay_ms;
size_t sz = sizeof(ssize_t); size_t sz = sizeof(ssize_t);
assert_d_eq(mallctl("arena.0.dirty_decay_time", assert_d_eq(mallctl("arena.0.dirty_decay_ms",
(void *)&orig_dirty_decay_time, &sz, NULL, 0), 0, (void *)&orig_dirty_decay_ms, &sz, NULL, 0), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
dirty_decay_time = -2; dirty_decay_ms = -2;
assert_d_eq(mallctl("arena.0.dirty_decay_time", NULL, NULL, assert_d_eq(mallctl("arena.0.dirty_decay_ms", NULL, NULL,
(void *)&dirty_decay_time, sizeof(ssize_t)), EFAULT, (void *)&dirty_decay_ms, sizeof(ssize_t)), EFAULT,
"Unexpected mallctl() success"); "Unexpected mallctl() success");
dirty_decay_time = 0x7fffffff; dirty_decay_ms = 0x7fffffff;
assert_d_eq(mallctl("arena.0.dirty_decay_time", NULL, NULL, assert_d_eq(mallctl("arena.0.dirty_decay_ms", NULL, NULL,
(void *)&dirty_decay_time, sizeof(ssize_t)), 0, (void *)&dirty_decay_ms, sizeof(ssize_t)), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
for (prev_dirty_decay_time = dirty_decay_time, dirty_decay_time = -1; for (prev_dirty_decay_ms = dirty_decay_ms, dirty_decay_ms = -1;
dirty_decay_time < 20; prev_dirty_decay_time = dirty_decay_time, dirty_decay_ms < 20; prev_dirty_decay_ms = dirty_decay_ms,
dirty_decay_time++) { dirty_decay_ms++) {
ssize_t old_dirty_decay_time; ssize_t old_dirty_decay_ms;
assert_d_eq(mallctl("arena.0.dirty_decay_time", assert_d_eq(mallctl("arena.0.dirty_decay_ms",
(void *)&old_dirty_decay_time, &sz, (void *)&old_dirty_decay_ms, &sz, (void *)&dirty_decay_ms,
(void *)&dirty_decay_time, sizeof(ssize_t)), 0, sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
"Unexpected mallctl() failure"); assert_zd_eq(old_dirty_decay_ms, prev_dirty_decay_ms,
assert_zd_eq(old_dirty_decay_time, prev_dirty_decay_time, "Unexpected old arena.0.dirty_decay_ms");
"Unexpected old arena.0.dirty_decay_time");
} }
} }
TEST_END TEST_END
TEST_BEGIN(test_arena_i_muzzy_decay_time) { TEST_BEGIN(test_arena_i_muzzy_decay_ms) {
ssize_t muzzy_decay_time, orig_muzzy_decay_time, prev_muzzy_decay_time; ssize_t muzzy_decay_ms, orig_muzzy_decay_ms, prev_muzzy_decay_ms;
size_t sz = sizeof(ssize_t); size_t sz = sizeof(ssize_t);
assert_d_eq(mallctl("arena.0.muzzy_decay_time", assert_d_eq(mallctl("arena.0.muzzy_decay_ms",
(void *)&orig_muzzy_decay_time, &sz, NULL, 0), 0, (void *)&orig_muzzy_decay_ms, &sz, NULL, 0), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
muzzy_decay_time = -2; muzzy_decay_ms = -2;
assert_d_eq(mallctl("arena.0.muzzy_decay_time", NULL, NULL, assert_d_eq(mallctl("arena.0.muzzy_decay_ms", NULL, NULL,
(void *)&muzzy_decay_time, sizeof(ssize_t)), EFAULT, (void *)&muzzy_decay_ms, sizeof(ssize_t)), EFAULT,
"Unexpected mallctl() success"); "Unexpected mallctl() success");
muzzy_decay_time = 0x7fffffff; muzzy_decay_ms = 0x7fffffff;
assert_d_eq(mallctl("arena.0.muzzy_decay_time", NULL, NULL, assert_d_eq(mallctl("arena.0.muzzy_decay_ms", NULL, NULL,
(void *)&muzzy_decay_time, sizeof(ssize_t)), 0, (void *)&muzzy_decay_ms, sizeof(ssize_t)), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
for (prev_muzzy_decay_time = muzzy_decay_time, muzzy_decay_time = -1; for (prev_muzzy_decay_ms = muzzy_decay_ms, muzzy_decay_ms = -1;
muzzy_decay_time < 20; prev_muzzy_decay_time = muzzy_decay_time, muzzy_decay_ms < 20; prev_muzzy_decay_ms = muzzy_decay_ms,
muzzy_decay_time++) { muzzy_decay_ms++) {
ssize_t old_muzzy_decay_time; ssize_t old_muzzy_decay_ms;
assert_d_eq(mallctl("arena.0.muzzy_decay_time", assert_d_eq(mallctl("arena.0.muzzy_decay_ms",
(void *)&old_muzzy_decay_time, &sz, (void *)&old_muzzy_decay_ms, &sz, (void *)&muzzy_decay_ms,
(void *)&muzzy_decay_time, sizeof(ssize_t)), 0, sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
"Unexpected mallctl() failure"); assert_zd_eq(old_muzzy_decay_ms, prev_muzzy_decay_ms,
assert_zd_eq(old_muzzy_decay_time, prev_muzzy_decay_time, "Unexpected old arena.0.muzzy_decay_ms");
"Unexpected old arena.0.muzzy_decay_time");
} }
} }
TEST_END TEST_END
@ -555,68 +553,66 @@ TEST_BEGIN(test_arena_i_dss) {
} }
TEST_END TEST_END
TEST_BEGIN(test_arenas_dirty_decay_time) { TEST_BEGIN(test_arenas_dirty_decay_ms) {
ssize_t dirty_decay_time, orig_dirty_decay_time, prev_dirty_decay_time; ssize_t dirty_decay_ms, orig_dirty_decay_ms, prev_dirty_decay_ms;
size_t sz = sizeof(ssize_t); size_t sz = sizeof(ssize_t);
assert_d_eq(mallctl("arenas.dirty_decay_time", assert_d_eq(mallctl("arenas.dirty_decay_ms",
(void *)&orig_dirty_decay_time, &sz, NULL, 0), 0, (void *)&orig_dirty_decay_ms, &sz, NULL, 0), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
dirty_decay_time = -2; dirty_decay_ms = -2;
assert_d_eq(mallctl("arenas.dirty_decay_time", NULL, NULL, assert_d_eq(mallctl("arenas.dirty_decay_ms", NULL, NULL,
(void *)&dirty_decay_time, sizeof(ssize_t)), EFAULT, (void *)&dirty_decay_ms, sizeof(ssize_t)), EFAULT,
"Unexpected mallctl() success"); "Unexpected mallctl() success");
dirty_decay_time = 0x7fffffff; dirty_decay_ms = 0x7fffffff;
assert_d_eq(mallctl("arenas.dirty_decay_time", NULL, NULL, assert_d_eq(mallctl("arenas.dirty_decay_ms", NULL, NULL,
(void *)&dirty_decay_time, sizeof(ssize_t)), 0, (void *)&dirty_decay_ms, sizeof(ssize_t)), 0,
"Expected mallctl() failure"); "Expected mallctl() failure");
for (prev_dirty_decay_time = dirty_decay_time, dirty_decay_time = -1; for (prev_dirty_decay_ms = dirty_decay_ms, dirty_decay_ms = -1;
dirty_decay_time < 20; prev_dirty_decay_time = dirty_decay_time, dirty_decay_ms < 20; prev_dirty_decay_ms = dirty_decay_ms,
dirty_decay_time++) { dirty_decay_ms++) {
ssize_t old_dirty_decay_time; ssize_t old_dirty_decay_ms;
assert_d_eq(mallctl("arenas.dirty_decay_time", assert_d_eq(mallctl("arenas.dirty_decay_ms",
(void *)&old_dirty_decay_time, &sz, (void *)&old_dirty_decay_ms, &sz, (void *)&dirty_decay_ms,
(void *)&dirty_decay_time, sizeof(ssize_t)), 0, sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
"Unexpected mallctl() failure"); assert_zd_eq(old_dirty_decay_ms, prev_dirty_decay_ms,
assert_zd_eq(old_dirty_decay_time, prev_dirty_decay_time, "Unexpected old arenas.dirty_decay_ms");
"Unexpected old arenas.dirty_decay_time");
} }
} }
TEST_END TEST_END
TEST_BEGIN(test_arenas_muzzy_decay_time) { TEST_BEGIN(test_arenas_muzzy_decay_ms) {
ssize_t muzzy_decay_time, orig_muzzy_decay_time, prev_muzzy_decay_time; ssize_t muzzy_decay_ms, orig_muzzy_decay_ms, prev_muzzy_decay_ms;
size_t sz = sizeof(ssize_t); size_t sz = sizeof(ssize_t);
assert_d_eq(mallctl("arenas.muzzy_decay_time", assert_d_eq(mallctl("arenas.muzzy_decay_ms",
(void *)&orig_muzzy_decay_time, &sz, NULL, 0), 0, (void *)&orig_muzzy_decay_ms, &sz, NULL, 0), 0,
"Unexpected mallctl() failure"); "Unexpected mallctl() failure");
muzzy_decay_time = -2; muzzy_decay_ms = -2;
assert_d_eq(mallctl("arenas.muzzy_decay_time", NULL, NULL, assert_d_eq(mallctl("arenas.muzzy_decay_ms", NULL, NULL,
(void *)&muzzy_decay_time, sizeof(ssize_t)), EFAULT, (void *)&muzzy_decay_ms, sizeof(ssize_t)), EFAULT,
"Unexpected mallctl() success"); "Unexpected mallctl() success");
muzzy_decay_time = 0x7fffffff; muzzy_decay_ms = 0x7fffffff;
assert_d_eq(mallctl("arenas.muzzy_decay_time", NULL, NULL, assert_d_eq(mallctl("arenas.muzzy_decay_ms", NULL, NULL,
(void *)&muzzy_decay_time, sizeof(ssize_t)), 0, (void *)&muzzy_decay_ms, sizeof(ssize_t)), 0,
"Expected mallctl() failure"); "Expected mallctl() failure");
for (prev_muzzy_decay_time = muzzy_decay_time, muzzy_decay_time = -1; for (prev_muzzy_decay_ms = muzzy_decay_ms, muzzy_decay_ms = -1;
muzzy_decay_time < 20; prev_muzzy_decay_time = muzzy_decay_time, muzzy_decay_ms < 20; prev_muzzy_decay_ms = muzzy_decay_ms,
muzzy_decay_time++) { muzzy_decay_ms++) {
ssize_t old_muzzy_decay_time; ssize_t old_muzzy_decay_ms;
assert_d_eq(mallctl("arenas.muzzy_decay_time", assert_d_eq(mallctl("arenas.muzzy_decay_ms",
(void *)&old_muzzy_decay_time, &sz, (void *)&old_muzzy_decay_ms, &sz, (void *)&muzzy_decay_ms,
(void *)&muzzy_decay_time, sizeof(ssize_t)), 0, sizeof(ssize_t)), 0, "Unexpected mallctl() failure");
"Unexpected mallctl() failure"); assert_zd_eq(old_muzzy_decay_ms, prev_muzzy_decay_ms,
assert_zd_eq(old_muzzy_decay_time, prev_muzzy_decay_time, "Unexpected old arenas.muzzy_decay_ms");
"Unexpected old arenas.muzzy_decay_time");
} }
} }
TEST_END TEST_END
@ -699,8 +695,8 @@ TEST_BEGIN(test_stats_arenas) {
TEST_STATS_ARENAS(unsigned, nthreads); TEST_STATS_ARENAS(unsigned, nthreads);
TEST_STATS_ARENAS(const char *, dss); TEST_STATS_ARENAS(const char *, dss);
TEST_STATS_ARENAS(ssize_t, dirty_decay_time); TEST_STATS_ARENAS(ssize_t, dirty_decay_ms);
TEST_STATS_ARENAS(ssize_t, muzzy_decay_time); TEST_STATS_ARENAS(ssize_t, muzzy_decay_ms);
TEST_STATS_ARENAS(size_t, pactive); TEST_STATS_ARENAS(size_t, pactive);
TEST_STATS_ARENAS(size_t, pdirty); TEST_STATS_ARENAS(size_t, pdirty);
@ -723,13 +719,13 @@ main(void) {
test_tcache, test_tcache,
test_thread_arena, test_thread_arena,
test_arena_i_initialized, test_arena_i_initialized,
test_arena_i_dirty_decay_time, test_arena_i_dirty_decay_ms,
test_arena_i_muzzy_decay_time, test_arena_i_muzzy_decay_ms,
test_arena_i_purge, test_arena_i_purge,
test_arena_i_decay, test_arena_i_decay,
test_arena_i_dss, test_arena_i_dss,
test_arenas_dirty_decay_time, test_arenas_dirty_decay_ms,
test_arenas_muzzy_decay_time, test_arenas_muzzy_decay_ms,
test_arenas_constants, test_arenas_constants,
test_arenas_bin_constants, test_arenas_bin_constants,
test_arenas_lextent_constants, test_arenas_lextent_constants,

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
# Immediately purge to minimize fragmentation. # Immediately purge to minimize fragmentation.
export MALLOC_CONF="dirty_decay_time:0,muzzy_decay_time:0" export MALLOC_CONF="dirty_decay_ms:0,muzzy_decay_ms:0"