Implement interval-based heap profile dumping.
Add mallctl interfaces for profiling parameters. Fix a file descriptor leak in heap profile dumping.
This commit is contained in:
parent
b01a6c2057
commit
d34f9e7e93
@ -388,12 +388,11 @@ will disable dirty page purging.
|
|||||||
@roff_tcache@Note that one cache slot per size class is not a valid
|
@roff_tcache@Note that one cache slot per size class is not a valid
|
||||||
@roff_tcache@configuration due to implementation details.
|
@roff_tcache@configuration due to implementation details.
|
||||||
@roff_prof@.It I
|
@roff_prof@.It I
|
||||||
@roff_prof@Double/halve the maximum interval between memory profile dumps, as
|
@roff_prof@Double/halve the average interval between memory profile dumps, as
|
||||||
@roff_prof@measured in bytes of allocation activity.
|
@roff_prof@measured in bytes of allocation activity.
|
||||||
@roff_prof@On average, profiles are written four times as often as the maximum
|
@roff_prof@The actual interval between dumps may be sporadic because
|
||||||
@roff_prof@interval requires.
|
@roff_prof@decentralized allocation counters are used to avoid synchronization
|
||||||
@roff_prof@This is an artifact of the concurrent algorithm that is used to
|
@roff_prof@bottlenecks.
|
||||||
@roff_prof@track allocation activity.
|
|
||||||
@roff_prof@Profiles are dumped to files named according to the pattern
|
@roff_prof@Profiles are dumped to files named according to the pattern
|
||||||
@roff_prof@.Pa <prefix>.<pid>.<seq>.i<iseq>.heap ,
|
@roff_prof@.Pa <prefix>.<pid>.<seq>.i<iseq>.heap ,
|
||||||
@roff_prof@where
|
@roff_prof@where
|
||||||
@ -401,7 +400,7 @@ will disable dirty page purging.
|
|||||||
@roff_prof@is controlled by the
|
@roff_prof@is controlled by the
|
||||||
@roff_prof@JEMALLOC_PROF_PREFIX
|
@roff_prof@JEMALLOC_PROF_PREFIX
|
||||||
@roff_prof@environment variable.
|
@roff_prof@environment variable.
|
||||||
@roff_prof@The default maximum interval is 4 GiB.
|
@roff_prof@The default average interval is 1 GiB.
|
||||||
@roff_fill@.It J
|
@roff_fill@.It J
|
||||||
@roff_fill@Each byte of new memory allocated by
|
@roff_fill@Each byte of new memory allocated by
|
||||||
@roff_fill@.Fn @jemalloc_prefix@malloc
|
@roff_fill@.Fn @jemalloc_prefix@malloc
|
||||||
@ -693,6 +692,21 @@ This is useful for detecting whether another thread caused a refresh.
|
|||||||
--enable-lazy-lock was specified during build configuration.
|
--enable-lazy-lock was specified during build configuration.
|
||||||
.Ed
|
.Ed
|
||||||
.\"-----------------------------------------------------------------------------
|
.\"-----------------------------------------------------------------------------
|
||||||
|
.It Sy "config.prof (bool) r-"
|
||||||
|
.Bd -ragged -offset indent -compact
|
||||||
|
--enable-prof was specified during build configuration.
|
||||||
|
.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
.It Sy "config.prof_libgcc (bool) r-"
|
||||||
|
.Bd -ragged -offset indent -compact
|
||||||
|
--disable-prof-libgcc was not specified during build configuration.
|
||||||
|
.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
.It Sy "config.prof_libunwind (bool) r-"
|
||||||
|
.Bd -ragged -offset indent -compact
|
||||||
|
--enable-prof-libunwind was specified during build configuration.
|
||||||
|
.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
.It Sy "config.stats (bool) r-"
|
.It Sy "config.stats (bool) r-"
|
||||||
.Bd -ragged -offset indent -compact
|
.Bd -ragged -offset indent -compact
|
||||||
--enable-stats was specified during build configuration.
|
--enable-stats was specified during build configuration.
|
||||||
@ -782,6 +796,41 @@ See the
|
|||||||
option.
|
option.
|
||||||
.Ed
|
.Ed
|
||||||
.\"-----------------------------------------------------------------------------
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "opt.prof (bool) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq F
|
||||||
|
@roff_prof@option.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "opt.lg_prof_bt_max (size_t) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq B
|
||||||
|
@roff_prof@option.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "opt.lg_prof_interval (size_t) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq I
|
||||||
|
@roff_prof@option.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "opt.prof_udump (bool) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq U
|
||||||
|
@roff_prof@option.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "opt.prof_leak (bool) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq L
|
||||||
|
@roff_prof@option.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
@roff_trace@.It Sy "opt.trace (bool) r-"
|
@roff_trace@.It Sy "opt.trace (bool) r-"
|
||||||
@roff_trace@.Bd -ragged -offset indent -compact
|
@roff_trace@.Bd -ragged -offset indent -compact
|
||||||
@roff_trace@See the
|
@roff_trace@See the
|
||||||
@ -993,6 +1042,15 @@ Maximum size supported by this large size class.
|
|||||||
@roff_prof@environment variable.
|
@roff_prof@environment variable.
|
||||||
@roff_prof@.Ed
|
@roff_prof@.Ed
|
||||||
.\"-----------------------------------------------------------------------------
|
.\"-----------------------------------------------------------------------------
|
||||||
|
@roff_prof@.It Sy "prof.interval (uint64_t) r-"
|
||||||
|
@roff_prof@.Bd -ragged -offset indent -compact
|
||||||
|
@roff_prof@Average number of bytes allocated between inverval-based profile
|
||||||
|
@roff_prof@dumps.
|
||||||
|
@roff_prof@See the
|
||||||
|
@roff_prof@.Dq I
|
||||||
|
@roff_prof@option for additional information.
|
||||||
|
@roff_prof@.Ed
|
||||||
|
.\"-----------------------------------------------------------------------------
|
||||||
@roff_stats@.It Sy "stats.allocated (size_t) r-"
|
@roff_stats@.It Sy "stats.allocated (size_t) r-"
|
||||||
@roff_stats@.Bd -ragged -offset indent -compact
|
@roff_stats@.Bd -ragged -offset indent -compact
|
||||||
@roff_stats@Total number of bytes allocated by the application.
|
@roff_stats@Total number of bytes allocated by the application.
|
||||||
|
@ -290,6 +290,10 @@ struct arena_s {
|
|||||||
int trace_fd;
|
int trace_fd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
uint64_t prof_accumbytes;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Tree of dirty-page-containing chunks this arena manages. */
|
/* Tree of dirty-page-containing chunks this arena manages. */
|
||||||
arena_chunk_tree_t chunks_dirty;
|
arena_chunk_tree_t chunks_dirty;
|
||||||
|
|
||||||
@ -411,7 +415,14 @@ extern size_t mspace_mask;
|
|||||||
#define nlclasses ((chunksize - PAGE_SIZE) >> PAGE_SHIFT)
|
#define nlclasses ((chunksize - PAGE_SIZE) >> PAGE_SHIFT)
|
||||||
|
|
||||||
#ifdef JEMALLOC_TCACHE
|
#ifdef JEMALLOC_TCACHE
|
||||||
void arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind);
|
void arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind
|
||||||
|
# ifdef JEMALLOC_PROF
|
||||||
|
, uint64_t prof_accumbytes
|
||||||
|
# endif
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
void arena_prof_accum(arena_t *arena, uint64_t accumbytes);
|
||||||
#endif
|
#endif
|
||||||
void *arena_malloc_small(arena_t *arena, size_t size, bool zero);
|
void *arena_malloc_small(arena_t *arena, size_t size, bool zero);
|
||||||
void *arena_malloc_medium(arena_t *arena, size_t size, bool zero);
|
void *arena_malloc_medium(arena_t *arena, size_t size, bool zero);
|
||||||
|
@ -35,6 +35,9 @@ struct tcache_bin_s {
|
|||||||
struct tcache_s {
|
struct tcache_s {
|
||||||
# ifdef JEMALLOC_STATS
|
# ifdef JEMALLOC_STATS
|
||||||
ql_elm(tcache_t) link; /* Used for aggregating stats. */
|
ql_elm(tcache_t) link; /* Used for aggregating stats. */
|
||||||
|
# endif
|
||||||
|
# ifdef JEMALLOC_PROF
|
||||||
|
uint64_t prof_accumbytes;/* Cleared after arena_prof_accum() */
|
||||||
# endif
|
# endif
|
||||||
arena_t *arena; /* This thread's arena. */
|
arena_t *arena; /* This thread's arena. */
|
||||||
unsigned ev_cnt; /* Event count since incremental GC. */
|
unsigned ev_cnt; /* Event count since incremental GC. */
|
||||||
@ -62,7 +65,11 @@ extern size_t tcache_nslots;
|
|||||||
/* Number of tcache allocation/deallocation events between incremental GCs. */
|
/* Number of tcache allocation/deallocation events between incremental GCs. */
|
||||||
extern unsigned tcache_gc_incr;
|
extern unsigned tcache_gc_incr;
|
||||||
|
|
||||||
void tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem);
|
void tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache_t *tcache
|
||||||
|
#endif
|
||||||
|
);
|
||||||
tcache_t *tcache_create(arena_t *arena);
|
tcache_t *tcache_create(arena_t *arena);
|
||||||
void tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin,
|
void tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin,
|
||||||
unsigned binind);
|
unsigned binind);
|
||||||
@ -138,7 +145,11 @@ tcache_event(tcache_t *tcache)
|
|||||||
*/
|
*/
|
||||||
tcache_bin_flush(tbin, binind,
|
tcache_bin_flush(tbin, binind,
|
||||||
tbin->ncached - (tbin->low_water >>
|
tbin->ncached - (tbin->low_water >>
|
||||||
1) - (tbin->low_water & 1));
|
1) - (tbin->low_water & 1)
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
tbin->low_water = tbin->ncached;
|
tbin->low_water = tbin->ncached;
|
||||||
tbin->high_water = tbin->ncached;
|
tbin->high_water = tbin->ncached;
|
||||||
@ -205,6 +216,9 @@ tcache_alloc(tcache_t *tcache, size_t size, bool zero)
|
|||||||
|
|
||||||
#ifdef JEMALLOC_STATS
|
#ifdef JEMALLOC_STATS
|
||||||
tbin->tstats.nrequests++;
|
tbin->tstats.nrequests++;
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
tcache->prof_accumbytes += tcache->arena->bins[binind].reg_size;
|
||||||
#endif
|
#endif
|
||||||
tcache_event(tcache);
|
tcache_event(tcache);
|
||||||
return (ret);
|
return (ret);
|
||||||
@ -252,7 +266,11 @@ tcache_dalloc(tcache_t *tcache, void *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tbin->ncached == tcache_nslots)
|
if (tbin->ncached == tcache_nslots)
|
||||||
tcache_bin_flush(tbin, binind, (tcache_nslots >> 1));
|
tcache_bin_flush(tbin, binind, (tcache_nslots >> 1)
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache
|
||||||
|
#endif
|
||||||
|
);
|
||||||
assert(tbin->ncached < tcache_nslots);
|
assert(tbin->ncached < tcache_nslots);
|
||||||
tbin->slots[tbin->ncached] = ptr;
|
tbin->slots[tbin->ncached] = ptr;
|
||||||
tbin->ncached++;
|
tbin->ncached++;
|
||||||
|
@ -8,7 +8,7 @@ typedef struct prof_thr_cnt_s prof_thr_cnt_t;
|
|||||||
typedef struct prof_ctx_s prof_ctx_t;
|
typedef struct prof_ctx_s prof_ctx_t;
|
||||||
typedef struct prof_s prof_t;
|
typedef struct prof_s prof_t;
|
||||||
|
|
||||||
#define LG_PROF_INTERVAL_DEFAULT 32
|
#define LG_PROF_INTERVAL_DEFAULT 30
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hard limit on stack backtrace depth. Note that the version of
|
* Hard limit on stack backtrace depth. Note that the version of
|
||||||
@ -121,6 +121,15 @@ extern size_t opt_lg_prof_interval;
|
|||||||
extern bool opt_prof_udump; /* High-water memory dumping. */
|
extern bool opt_prof_udump; /* High-water memory dumping. */
|
||||||
extern bool opt_prof_leak; /* Dump leak summary at exit. */
|
extern bool opt_prof_leak; /* Dump leak summary at exit. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Profile dump interval, measured in bytes allocated. Each arena triggers a
|
||||||
|
* profile dump when it reaches this threshold. The effect is that the
|
||||||
|
* interval between profile dumps averages prof_interval, though the actual
|
||||||
|
* interval between dumps will tend to be sporadic, and the interval will be a
|
||||||
|
* maximum of approximately (prof_interval * narenas).
|
||||||
|
*/
|
||||||
|
extern uint64_t prof_interval;
|
||||||
|
|
||||||
bool prof_init(prof_t *prof, bool master);
|
bool prof_init(prof_t *prof, bool master);
|
||||||
void prof_destroy(prof_t *prof);
|
void prof_destroy(prof_t *prof);
|
||||||
|
|
||||||
@ -135,7 +144,6 @@ void prof_mdump(void);
|
|||||||
void prof_udump(void);
|
void prof_udump(void);
|
||||||
void prof_boot0(void);
|
void prof_boot0(void);
|
||||||
bool prof_boot1(void);
|
bool prof_boot1(void);
|
||||||
void prof_boot2(void);
|
|
||||||
|
|
||||||
#endif /* JEMALLOC_H_EXTERNS */
|
#endif /* JEMALLOC_H_EXTERNS */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
*
|
*
|
||||||
* Allocation requests are rounded up to the nearest size class, and no record
|
* Allocation requests are rounded up to the nearest size class, and no record
|
||||||
* of the original request size is maintained. Allocations are broken into
|
* of the original request size is maintained. Allocations are broken into
|
||||||
* categories according to size class. Assuming runtime defaults, 4 KiB pages
|
* categories according to size class. Assuming 1 MiB chunks, 4 KiB pages and
|
||||||
* and a 16 byte quantum on a 32-bit system, the size classes in each category
|
* a 16 byte quantum on a 32-bit system, the size classes in each category are
|
||||||
* are as follows:
|
* as follows:
|
||||||
*
|
*
|
||||||
* |========================================|
|
* |========================================|
|
||||||
* | Category | Subcategory | Size |
|
* | Category | Subcategory | Size |
|
||||||
@ -822,10 +822,6 @@ MALLOC_OUT:
|
|||||||
next_arena = 0;
|
next_arena = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_PROF
|
|
||||||
prof_boot2();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Allocate and initialize arenas. */
|
/* Allocate and initialize arenas. */
|
||||||
arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
|
arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
|
||||||
if (arenas == NULL) {
|
if (arenas == NULL) {
|
||||||
|
@ -1031,7 +1031,11 @@ arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
|
|||||||
|
|
||||||
#ifdef JEMALLOC_TCACHE
|
#ifdef JEMALLOC_TCACHE
|
||||||
void
|
void
|
||||||
arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind)
|
arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind
|
||||||
|
# ifdef JEMALLOC_PROF
|
||||||
|
, uint64_t prof_accumbytes
|
||||||
|
# endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
unsigned i, nfill;
|
unsigned i, nfill;
|
||||||
arena_bin_t *bin;
|
arena_bin_t *bin;
|
||||||
@ -1042,6 +1046,9 @@ arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind)
|
|||||||
|
|
||||||
bin = &arena->bins[binind];
|
bin = &arena->bins[binind];
|
||||||
malloc_mutex_lock(&arena->lock);
|
malloc_mutex_lock(&arena->lock);
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
arena_prof_accum(arena, prof_accumbytes);
|
||||||
|
#endif
|
||||||
for (i = 0, nfill = (tcache_nslots >> 1); i < nfill; i++) {
|
for (i = 0, nfill = (tcache_nslots >> 1); i < nfill; i++) {
|
||||||
if ((run = bin->runcur) != NULL && run->nfree > 0)
|
if ((run = bin->runcur) != NULL && run->nfree > 0)
|
||||||
ptr = arena_bin_malloc_easy(arena, bin, run);
|
ptr = arena_bin_malloc_easy(arena, bin, run);
|
||||||
@ -1088,6 +1095,19 @@ arena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
void
|
||||||
|
arena_prof_accum(arena_t *arena, uint64_t accumbytes)
|
||||||
|
{
|
||||||
|
|
||||||
|
arena->prof_accumbytes += accumbytes;
|
||||||
|
if (arena->prof_accumbytes >= prof_interval) {
|
||||||
|
prof_idump();
|
||||||
|
arena->prof_accumbytes -= prof_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate bin->run_size such that it meets the following constraints:
|
* Calculate bin->run_size such that it meets the following constraints:
|
||||||
*
|
*
|
||||||
@ -1243,6 +1263,10 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
arena->stats.allocated_small += size;
|
arena->stats.allocated_small += size;
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
if (isthreaded == false)
|
||||||
|
arena_prof_accum(arena, size);
|
||||||
#endif
|
#endif
|
||||||
malloc_mutex_unlock(&arena->lock);
|
malloc_mutex_unlock(&arena->lock);
|
||||||
|
|
||||||
@ -1294,6 +1318,10 @@ arena_malloc_medium(arena_t *arena, size_t size, bool zero)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
arena->stats.allocated_medium += size;
|
arena->stats.allocated_medium += size;
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
if (isthreaded == false)
|
||||||
|
arena_prof_accum(arena, size);
|
||||||
#endif
|
#endif
|
||||||
malloc_mutex_unlock(&arena->lock);
|
malloc_mutex_unlock(&arena->lock);
|
||||||
|
|
||||||
@ -1333,6 +1361,9 @@ arena_malloc_large(arena_t *arena, size_t size, bool zero)
|
|||||||
arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
|
arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
|
||||||
arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
|
arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
arena_prof_accum(arena, size);
|
||||||
#endif
|
#endif
|
||||||
malloc_mutex_unlock(&arena->lock);
|
malloc_mutex_unlock(&arena->lock);
|
||||||
|
|
||||||
@ -2035,6 +2066,10 @@ arena_new(arena_t *arena, unsigned ind)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
arena->prof_accumbytes = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialize chunks. */
|
/* Initialize chunks. */
|
||||||
arena_chunk_tree_dirty_new(&arena->chunks_dirty);
|
arena_chunk_tree_dirty_new(&arena->chunks_dirty);
|
||||||
arena->spare = NULL;
|
arena->spare = NULL;
|
||||||
|
@ -34,14 +34,14 @@ CTL_PROTO(epoch)
|
|||||||
#ifdef JEMALLOC_TCACHE
|
#ifdef JEMALLOC_TCACHE
|
||||||
CTL_PROTO(tcache_flush)
|
CTL_PROTO(tcache_flush)
|
||||||
#endif
|
#endif
|
||||||
#ifdef JEMALLOC_PROF
|
|
||||||
CTL_PROTO(prof_dump)
|
|
||||||
#endif
|
|
||||||
CTL_PROTO(config_debug)
|
CTL_PROTO(config_debug)
|
||||||
CTL_PROTO(config_dss)
|
CTL_PROTO(config_dss)
|
||||||
CTL_PROTO(config_dynamic_page_shift)
|
CTL_PROTO(config_dynamic_page_shift)
|
||||||
CTL_PROTO(config_fill)
|
CTL_PROTO(config_fill)
|
||||||
CTL_PROTO(config_lazy_lock)
|
CTL_PROTO(config_lazy_lock)
|
||||||
|
CTL_PROTO(config_prof)
|
||||||
|
CTL_PROTO(config_prof_libgcc)
|
||||||
|
CTL_PROTO(config_prof_libunwind)
|
||||||
CTL_PROTO(config_stats)
|
CTL_PROTO(config_stats)
|
||||||
CTL_PROTO(config_swap)
|
CTL_PROTO(config_swap)
|
||||||
CTL_PROTO(config_sysv)
|
CTL_PROTO(config_sysv)
|
||||||
@ -67,6 +67,13 @@ CTL_PROTO(opt_zero)
|
|||||||
CTL_PROTO(opt_lg_tcache_nslots)
|
CTL_PROTO(opt_lg_tcache_nslots)
|
||||||
CTL_PROTO(opt_lg_tcache_gc_sweep)
|
CTL_PROTO(opt_lg_tcache_gc_sweep)
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
CTL_PROTO(opt_prof)
|
||||||
|
CTL_PROTO(opt_lg_prof_bt_max)
|
||||||
|
CTL_PROTO(opt_lg_prof_interval)
|
||||||
|
CTL_PROTO(opt_prof_udump)
|
||||||
|
CTL_PROTO(opt_prof_leak)
|
||||||
|
#endif
|
||||||
CTL_PROTO(opt_stats_print)
|
CTL_PROTO(opt_stats_print)
|
||||||
#ifdef JEMALLOC_TRACE
|
#ifdef JEMALLOC_TRACE
|
||||||
CTL_PROTO(opt_trace)
|
CTL_PROTO(opt_trace)
|
||||||
@ -112,6 +119,10 @@ CTL_PROTO(arenas_nsbins)
|
|||||||
CTL_PROTO(arenas_nmbins)
|
CTL_PROTO(arenas_nmbins)
|
||||||
CTL_PROTO(arenas_nbins)
|
CTL_PROTO(arenas_nbins)
|
||||||
CTL_PROTO(arenas_nlruns)
|
CTL_PROTO(arenas_nlruns)
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
CTL_PROTO(prof_dump)
|
||||||
|
CTL_PROTO(prof_interval)
|
||||||
|
#endif
|
||||||
#ifdef JEMALLOC_STATS
|
#ifdef JEMALLOC_STATS
|
||||||
CTL_PROTO(stats_chunks_current)
|
CTL_PROTO(stats_chunks_current)
|
||||||
CTL_PROTO(stats_chunks_total)
|
CTL_PROTO(stats_chunks_total)
|
||||||
@ -188,18 +199,15 @@ static const ctl_node_t tcache_node[] = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_PROF
|
|
||||||
static const ctl_node_t prof_node[] = {
|
|
||||||
{NAME("dump"), CTL(prof_dump)}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const ctl_node_t config_node[] = {
|
static const ctl_node_t config_node[] = {
|
||||||
{NAME("debug"), CTL(config_debug)},
|
{NAME("debug"), CTL(config_debug)},
|
||||||
{NAME("dss"), CTL(config_dss)},
|
{NAME("dss"), CTL(config_dss)},
|
||||||
{NAME("dynamic_page_shift"), CTL(config_dynamic_page_shift)},
|
{NAME("dynamic_page_shift"), CTL(config_dynamic_page_shift)},
|
||||||
{NAME("fill"), CTL(config_fill)},
|
{NAME("fill"), CTL(config_fill)},
|
||||||
{NAME("lazy_lock"), CTL(config_lazy_lock)},
|
{NAME("lazy_lock"), CTL(config_lazy_lock)},
|
||||||
|
{NAME("prof"), CTL(config_prof)},
|
||||||
|
{NAME("prof_libgcc"), CTL(config_prof_libgcc)},
|
||||||
|
{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
|
||||||
{NAME("stats"), CTL(config_stats)},
|
{NAME("stats"), CTL(config_stats)},
|
||||||
{NAME("swap"), CTL(config_swap)},
|
{NAME("swap"), CTL(config_swap)},
|
||||||
{NAME("sysv"), CTL(config_sysv)},
|
{NAME("sysv"), CTL(config_sysv)},
|
||||||
@ -227,6 +235,13 @@ static const ctl_node_t opt_node[] = {
|
|||||||
#ifdef JEMALLOC_TCACHE
|
#ifdef JEMALLOC_TCACHE
|
||||||
{NAME("lg_tcache_nslots"), CTL(opt_lg_tcache_nslots)},
|
{NAME("lg_tcache_nslots"), CTL(opt_lg_tcache_nslots)},
|
||||||
{NAME("lg_tcache_gc_sweep"), CTL(opt_lg_tcache_gc_sweep)},
|
{NAME("lg_tcache_gc_sweep"), CTL(opt_lg_tcache_gc_sweep)},
|
||||||
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
{NAME("prof"), CTL(opt_prof)},
|
||||||
|
{NAME("lg_prof_bt_max"), CTL(opt_lg_prof_bt_max)},
|
||||||
|
{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
|
||||||
|
{NAME("prof_udump"), CTL(opt_prof_udump)},
|
||||||
|
{NAME("prof_leak"), CTL(opt_prof_leak)},
|
||||||
#endif
|
#endif
|
||||||
{NAME("stats_print"), CTL(opt_stats_print)},
|
{NAME("stats_print"), CTL(opt_stats_print)},
|
||||||
#ifdef JEMALLOC_TRACE
|
#ifdef JEMALLOC_TRACE
|
||||||
@ -299,6 +314,13 @@ static const ctl_node_t arenas_node[] = {
|
|||||||
{NAME("lrun"), CHILD(arenas_lrun)}
|
{NAME("lrun"), CHILD(arenas_lrun)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
static const ctl_node_t prof_node[] = {
|
||||||
|
{NAME("dump"), CTL(prof_dump)},
|
||||||
|
{NAME("interval"), CTL(prof_interval)}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_STATS
|
#ifdef JEMALLOC_STATS
|
||||||
static const ctl_node_t stats_chunks_node[] = {
|
static const ctl_node_t stats_chunks_node[] = {
|
||||||
{NAME("current"), CTL(stats_chunks_current)},
|
{NAME("current"), CTL(stats_chunks_current)},
|
||||||
@ -413,13 +435,13 @@ static const ctl_node_t root_node[] = {
|
|||||||
{NAME("epoch"), CTL(epoch)},
|
{NAME("epoch"), CTL(epoch)},
|
||||||
#ifdef JEMALLOC_TCACHE
|
#ifdef JEMALLOC_TCACHE
|
||||||
{NAME("tcache"), CHILD(tcache)},
|
{NAME("tcache"), CHILD(tcache)},
|
||||||
#endif
|
|
||||||
#ifdef JEMALLOC_PROF
|
|
||||||
{NAME("prof"), CHILD(prof)},
|
|
||||||
#endif
|
#endif
|
||||||
{NAME("config"), CHILD(config)},
|
{NAME("config"), CHILD(config)},
|
||||||
{NAME("opt"), CHILD(opt)},
|
{NAME("opt"), CHILD(opt)},
|
||||||
{NAME("arenas"), CHILD(arenas)},
|
{NAME("arenas"), CHILD(arenas)},
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
{NAME("prof"), CHILD(prof)},
|
||||||
|
#endif
|
||||||
{NAME("stats"), CHILD(stats)}
|
{NAME("stats"), CHILD(stats)}
|
||||||
#ifdef JEMALLOC_SWAP
|
#ifdef JEMALLOC_SWAP
|
||||||
,
|
,
|
||||||
@ -938,23 +960,6 @@ RETURN:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_PROF
|
|
||||||
static int
|
|
||||||
prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
|
||||||
void *newp, size_t newlen)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
VOID();
|
|
||||||
|
|
||||||
prof_mdump();
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
RETURN:
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
#ifdef JEMALLOC_DEBUG
|
#ifdef JEMALLOC_DEBUG
|
||||||
@ -987,6 +992,24 @@ CTL_RO_TRUE_GEN(config_lazy_lock)
|
|||||||
CTL_RO_FALSE_GEN(config_lazy_lock)
|
CTL_RO_FALSE_GEN(config_lazy_lock)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
CTL_RO_TRUE_GEN(config_prof)
|
||||||
|
#else
|
||||||
|
CTL_RO_FALSE_GEN(config_prof)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF_LIBGCC
|
||||||
|
CTL_RO_TRUE_GEN(config_prof_libgcc)
|
||||||
|
#else
|
||||||
|
CTL_RO_FALSE_GEN(config_prof_libgcc)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF_LIBUNWIND
|
||||||
|
CTL_RO_TRUE_GEN(config_prof_libunwind)
|
||||||
|
#else
|
||||||
|
CTL_RO_FALSE_GEN(config_prof_libunwind)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_STATS
|
#ifdef JEMALLOC_STATS
|
||||||
CTL_RO_TRUE_GEN(config_stats)
|
CTL_RO_TRUE_GEN(config_stats)
|
||||||
#else
|
#else
|
||||||
@ -1054,6 +1077,13 @@ CTL_RO_GEN(opt_zero, opt_zero, bool)
|
|||||||
CTL_RO_GEN(opt_lg_tcache_nslots, opt_lg_tcache_nslots, size_t)
|
CTL_RO_GEN(opt_lg_tcache_nslots, opt_lg_tcache_nslots, size_t)
|
||||||
CTL_RO_GEN(opt_lg_tcache_gc_sweep, opt_lg_tcache_gc_sweep, ssize_t)
|
CTL_RO_GEN(opt_lg_tcache_gc_sweep, opt_lg_tcache_gc_sweep, ssize_t)
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
CTL_RO_GEN(opt_prof, opt_prof, bool)
|
||||||
|
CTL_RO_GEN(opt_lg_prof_bt_max, opt_lg_prof_bt_max, size_t)
|
||||||
|
CTL_RO_GEN(opt_lg_prof_interval, opt_lg_prof_interval, size_t)
|
||||||
|
CTL_RO_GEN(opt_prof_udump, opt_prof_udump, bool)
|
||||||
|
CTL_RO_GEN(opt_prof_leak, opt_prof_leak, bool)
|
||||||
|
#endif
|
||||||
CTL_RO_GEN(opt_stats_print, opt_stats_print, bool)
|
CTL_RO_GEN(opt_stats_print, opt_stats_print, bool)
|
||||||
#ifdef JEMALLOC_TRACE
|
#ifdef JEMALLOC_TRACE
|
||||||
CTL_RO_GEN(opt_trace, opt_trace, bool)
|
CTL_RO_GEN(opt_trace, opt_trace, bool)
|
||||||
@ -1145,6 +1175,27 @@ CTL_RO_GEN(arenas_nlruns, nlclasses, size_t)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
static int
|
||||||
|
prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||||
|
void *newp, size_t newlen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
VOID();
|
||||||
|
|
||||||
|
prof_mdump();
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
RETURN:
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTL_RO_GEN(prof_interval, prof_interval, uint64_t)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
#ifdef JEMALLOC_STATS
|
#ifdef JEMALLOC_STATS
|
||||||
CTL_RO_GEN(stats_chunks_current, ctl_stats.chunks.current, size_t)
|
CTL_RO_GEN(stats_chunks_current, ctl_stats.chunks.current, size_t)
|
||||||
CTL_RO_GEN(stats_chunks_total, ctl_stats.chunks.total, uint64_t)
|
CTL_RO_GEN(stats_chunks_total, ctl_stats.chunks.total, uint64_t)
|
||||||
|
@ -431,13 +431,19 @@ stats_print(void (*write4)(void *, const char *, const char *, const char *,
|
|||||||
write4(w4opaque, "Boolean JEMALLOC_OPTIONS: ", "", "", "");
|
write4(w4opaque, "Boolean JEMALLOC_OPTIONS: ", "", "", "");
|
||||||
if ((err = mallctl("opt.abort", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.abort", &bv, &bsz, NULL, 0)) == 0)
|
||||||
write4(w4opaque, bv ? "A" : "a", "", "", "");
|
write4(w4opaque, bv ? "A" : "a", "", "", "");
|
||||||
|
if ((err = mallctl("opt.prof", &bv, &bsz, NULL, 0)) == 0)
|
||||||
|
write4(w4opaque, bv ? "F" : "f", "", "", "");
|
||||||
if ((err = mallctl("opt.junk", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.junk", &bv, &bsz, NULL, 0)) == 0)
|
||||||
write4(w4opaque, bv ? "J" : "j", "", "", "");
|
write4(w4opaque, bv ? "J" : "j", "", "", "");
|
||||||
|
if ((err = mallctl("opt.prof_leak", &bv, &bsz, NULL, 0)) == 0)
|
||||||
|
write4(w4opaque, bv ? "L" : "l", "", "", "");
|
||||||
if ((err = mallctl("opt.overcommit", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.overcommit", &bv, &bsz, NULL, 0)) == 0)
|
||||||
write4(w4opaque, bv ? "O" : "o", "", "", "");
|
write4(w4opaque, bv ? "O" : "o", "", "", "");
|
||||||
write4(w4opaque, "P", "", "", "");
|
write4(w4opaque, "P", "", "", "");
|
||||||
if ((err = mallctl("opt.trace", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.trace", &bv, &bsz, NULL, 0)) == 0)
|
||||||
write4(w4opaque, bv ? "T" : "t", "", "", "");
|
write4(w4opaque, bv ? "T" : "t", "", "", "");
|
||||||
|
if ((err = mallctl("opt.prof_udump", &bv, &bsz, NULL, 0)) == 0)
|
||||||
|
write4(w4opaque, bv ? "U" : "u", "", "", "");
|
||||||
if ((err = mallctl("opt.sysv", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.sysv", &bv, &bsz, NULL, 0)) == 0)
|
||||||
write4(w4opaque, bv ? "V" : "v", "", "", "");
|
write4(w4opaque, bv ? "V" : "v", "", "", "");
|
||||||
if ((err = mallctl("opt.xmalloc", &bv, &bsz, NULL, 0)) == 0)
|
if ((err = mallctl("opt.xmalloc", &bv, &bsz, NULL, 0)) == 0)
|
||||||
@ -512,7 +518,6 @@ stats_print(void (*write4)(void *, const char *, const char *, const char *,
|
|||||||
"Min active:dirty page ratio per arena: N/A\n", "",
|
"Min active:dirty page ratio per arena: N/A\n", "",
|
||||||
"", "");
|
"", "");
|
||||||
}
|
}
|
||||||
#ifdef JEMALLOC_TCACHE
|
|
||||||
if ((err = mallctl("opt.lg_tcache_nslots", &sv, &ssz, NULL, 0))
|
if ((err = mallctl("opt.lg_tcache_nslots", &sv, &ssz, NULL, 0))
|
||||||
== 0) {
|
== 0) {
|
||||||
size_t tcache_nslots, tcache_gc_sweep;
|
size_t tcache_nslots, tcache_gc_sweep;
|
||||||
@ -528,7 +533,17 @@ stats_print(void (*write4)(void *, const char *, const char *, const char *,
|
|||||||
tcache_nslots && ssv >= 0 ? umax2s(tcache_gc_sweep,
|
tcache_nslots && ssv >= 0 ? umax2s(tcache_gc_sweep,
|
||||||
10, s) : "N/A", "\n", "");
|
10, s) : "N/A", "\n", "");
|
||||||
}
|
}
|
||||||
#endif
|
if ((err = mallctl("opt.lg_prof_bt_max", &sv, &ssz, NULL, 0))
|
||||||
|
== 0) {
|
||||||
|
write4(w4opaque, "Maximum profile backtrace depth: ",
|
||||||
|
umax2s((1U << sv), 10, s), "\n", "");
|
||||||
|
}
|
||||||
|
if ((err = mallctl("opt.lg_prof_interval", &sv, &ssz, NULL, 0))
|
||||||
|
== 0) {
|
||||||
|
write4(w4opaque, "Average profile dump interval: ",
|
||||||
|
umax2s((1U << sv), 10, s), "", "");
|
||||||
|
write4(w4opaque, " (2^", umax2s(sv, 10, s), ")\n", "");
|
||||||
|
}
|
||||||
CTL_GET("arenas.chunksize", &sv, size_t);
|
CTL_GET("arenas.chunksize", &sv, size_t);
|
||||||
write4(w4opaque, "Chunk size: ", umax2s(sv, 10, s), "", "");
|
write4(w4opaque, "Chunk size: ", umax2s(sv, 10, s), "", "");
|
||||||
CTL_GET("opt.lg_chunk", &sv, size_t);
|
CTL_GET("opt.lg_chunk", &sv, size_t);
|
||||||
|
@ -31,14 +31,25 @@ tcache_alloc_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind)
|
|||||||
{
|
{
|
||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
arena_tcache_fill(tcache->arena, tbin, binind);
|
arena_tcache_fill(tcache->arena, tbin, binind
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache->prof_accumbytes
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
tcache->prof_accumbytes = 0;
|
||||||
|
#endif
|
||||||
ret = tcache_bin_alloc(tbin);
|
ret = tcache_bin_alloc(tbin);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem)
|
tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache_t *tcache
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
arena_chunk_t *chunk;
|
arena_chunk_t *chunk;
|
||||||
arena_t *arena;
|
arena_t *arena;
|
||||||
@ -51,6 +62,12 @@ tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem)
|
|||||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(tbin->slots[0]);
|
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(tbin->slots[0]);
|
||||||
arena = chunk->arena;
|
arena = chunk->arena;
|
||||||
malloc_mutex_lock(&arena->lock);
|
malloc_mutex_lock(&arena->lock);
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
if (arena == tcache->arena) {
|
||||||
|
arena_prof_accum(arena, tcache->prof_accumbytes);
|
||||||
|
tcache->prof_accumbytes = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Deallocate every object that belongs to the locked arena. */
|
/* Deallocate every object that belongs to the locked arena. */
|
||||||
for (i = ndeferred = 0; i < ncached; i++) {
|
for (i = ndeferred = 0; i < ncached; i++) {
|
||||||
ptr = tbin->slots[i];
|
ptr = tbin->slots[i];
|
||||||
@ -216,11 +233,23 @@ tcache_destroy(tcache_t *tcache)
|
|||||||
for (i = 0; i < nbins; i++) {
|
for (i = 0; i < nbins; i++) {
|
||||||
tcache_bin_t *tbin = tcache->tbins[i];
|
tcache_bin_t *tbin = tcache->tbins[i];
|
||||||
if (tbin != NULL) {
|
if (tbin != NULL) {
|
||||||
tcache_bin_flush(tbin, i, 0);
|
tcache_bin_flush(tbin, i, 0
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
, tcache
|
||||||
|
#endif
|
||||||
|
);
|
||||||
tcache_bin_destroy(tcache, tbin, i);
|
tcache_bin_destroy(tcache, tbin, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JEMALLOC_PROF
|
||||||
|
if (tcache->prof_accumbytes > 0) {
|
||||||
|
malloc_mutex_lock(&tcache->arena->lock);
|
||||||
|
arena_prof_accum(tcache->arena, tcache->prof_accumbytes);
|
||||||
|
malloc_mutex_unlock(&tcache->arena->lock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (arena_salloc(tcache) <= bin_maxclass) {
|
if (arena_salloc(tcache) <= bin_maxclass) {
|
||||||
arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);
|
arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);
|
||||||
arena_t *arena = chunk->arena;
|
arena_t *arena = chunk->arena;
|
||||||
|
@ -21,6 +21,8 @@ size_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;
|
|||||||
bool opt_prof_udump = false;
|
bool opt_prof_udump = false;
|
||||||
bool opt_prof_leak = false;
|
bool opt_prof_leak = false;
|
||||||
|
|
||||||
|
uint64_t prof_interval;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global hash of (prof_bt_t *)-->(prof_ctx_t *). This is the master data
|
* Global hash of (prof_bt_t *)-->(prof_ctx_t *). This is the master data
|
||||||
* structure that knows about all backtraces ever captured.
|
* structure that knows about all backtraces ever captured.
|
||||||
@ -50,15 +52,6 @@ static pthread_key_t bt2cnt_tsd;
|
|||||||
/* (1U << opt_lg_prof_bt_max). */
|
/* (1U << opt_lg_prof_bt_max). */
|
||||||
static unsigned prof_bt_max;
|
static unsigned prof_bt_max;
|
||||||
|
|
||||||
/*
|
|
||||||
* Per arena profile dump interval, measured in bytes allocated. Each arena
|
|
||||||
* triggers a profile dump when it reaches this threshold. The effect is that
|
|
||||||
* the interval between profile dumps is never longer than (prof_interval *
|
|
||||||
* narenas), though the actual interval between dumps will tend to be sporadic,
|
|
||||||
* and the interval will on average be prof_interval.
|
|
||||||
*/
|
|
||||||
static uint64_t prof_interval;
|
|
||||||
|
|
||||||
static malloc_mutex_t prof_dump_seq_mtx;
|
static malloc_mutex_t prof_dump_seq_mtx;
|
||||||
static uint64_t prof_dump_seq;
|
static uint64_t prof_dump_seq;
|
||||||
static uint64_t prof_dump_iseq;
|
static uint64_t prof_dump_iseq;
|
||||||
@ -79,6 +72,7 @@ static bool prof_booted = false;
|
|||||||
|
|
||||||
static malloc_mutex_t enq_mtx;
|
static malloc_mutex_t enq_mtx;
|
||||||
static bool enq;
|
static bool enq;
|
||||||
|
static bool enq_idump;
|
||||||
static bool enq_udump;
|
static bool enq_udump;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -157,16 +151,20 @@ prof_enter(void)
|
|||||||
static inline void
|
static inline void
|
||||||
prof_leave(void)
|
prof_leave(void)
|
||||||
{
|
{
|
||||||
bool udump;
|
bool idump, udump;
|
||||||
|
|
||||||
malloc_mutex_unlock(&bt2ctx_mtx);
|
malloc_mutex_unlock(&bt2ctx_mtx);
|
||||||
|
|
||||||
malloc_mutex_lock(&enq_mtx);
|
malloc_mutex_lock(&enq_mtx);
|
||||||
enq = false;
|
enq = false;
|
||||||
|
idump = enq_idump;
|
||||||
|
enq_idump = false;
|
||||||
udump = enq_udump;
|
udump = enq_udump;
|
||||||
enq_udump = false;
|
enq_udump = false;
|
||||||
malloc_mutex_unlock(&enq_mtx);
|
malloc_mutex_unlock(&enq_mtx);
|
||||||
|
|
||||||
|
if (idump)
|
||||||
|
prof_idump();
|
||||||
if (udump)
|
if (udump)
|
||||||
prof_udump();
|
prof_udump();
|
||||||
}
|
}
|
||||||
@ -785,6 +783,7 @@ prof_dump_maps(void)
|
|||||||
nread = read(mfd, &prof_dump_buf[prof_dump_buf_end],
|
nread = read(mfd, &prof_dump_buf[prof_dump_buf_end],
|
||||||
PROF_DUMP_BUF_SIZE - prof_dump_buf_end);
|
PROF_DUMP_BUF_SIZE - prof_dump_buf_end);
|
||||||
} while (nread > 0);
|
} while (nread > 0);
|
||||||
|
close(mfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,6 +954,13 @@ prof_idump(void)
|
|||||||
|
|
||||||
if (prof_booted == false)
|
if (prof_booted == false)
|
||||||
return;
|
return;
|
||||||
|
malloc_mutex_lock(&enq_mtx);
|
||||||
|
if (enq) {
|
||||||
|
enq_idump = true;
|
||||||
|
malloc_mutex_unlock(&enq_mtx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
malloc_mutex_unlock(&enq_mtx);
|
||||||
|
|
||||||
malloc_mutex_lock(&prof_dump_seq_mtx);
|
malloc_mutex_lock(&prof_dump_seq_mtx);
|
||||||
prof_dump_filename(filename, 'i', prof_dump_iseq);
|
prof_dump_filename(filename, 'i', prof_dump_iseq);
|
||||||
@ -1134,6 +1140,7 @@ prof_boot1(void)
|
|||||||
if (malloc_mutex_init(&enq_mtx))
|
if (malloc_mutex_init(&enq_mtx))
|
||||||
return (true);
|
return (true);
|
||||||
enq = false;
|
enq = false;
|
||||||
|
enq_idump = false;
|
||||||
enq_udump = false;
|
enq_udump = false;
|
||||||
|
|
||||||
if (atexit(prof_fdump) != 0) {
|
if (atexit(prof_fdump) != 0) {
|
||||||
@ -1157,17 +1164,5 @@ prof_boot1(void)
|
|||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
prof_boot2(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (opt_prof) {
|
|
||||||
/*
|
|
||||||
* Finish initializing prof_interval, now that narenas is set.
|
|
||||||
*/
|
|
||||||
prof_interval /= narenas;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#endif /* JEMALLOC_PROF */
|
#endif /* JEMALLOC_PROF */
|
||||||
|
Loading…
Reference in New Issue
Block a user