Implement opt.stats_interval and the _opts options.
Add options stats_interval and stats_interval_opts to allow interval based stats printing. This provides an easy way to collect stats without code changes, because opt.stats_print may not work (some binaries never exit).
This commit is contained in:
@@ -6,11 +6,11 @@
|
||||
typedef struct counter_accum_s {
|
||||
#ifndef JEMALLOC_ATOMIC_U64
|
||||
malloc_mutex_t mtx;
|
||||
uint64_t accumbytes;
|
||||
uint64_t accumbytes;
|
||||
#else
|
||||
atomic_u64_t accumbytes;
|
||||
atomic_u64_t accumbytes;
|
||||
#endif
|
||||
uint64_t interval;
|
||||
uint64_t interval;
|
||||
} counter_accum_t;
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
@@ -52,7 +52,7 @@ counter_accum(tsdn_t *tsdn, counter_accum_t *counter, uint64_t accumbytes) {
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE void
|
||||
counter_rollback(tsdn_t *tsdn, counter_accum_t *counter, size_t usize) {
|
||||
counter_rollback(tsdn_t *tsdn, counter_accum_t *counter, uint64_t bytes) {
|
||||
/*
|
||||
* Cancel out as much of the excessive accumbytes increase as possible
|
||||
* without underflowing. Interval-triggered events occur slightly more
|
||||
@@ -63,16 +63,14 @@ counter_rollback(tsdn_t *tsdn, counter_accum_t *counter, size_t usize) {
|
||||
a0 = atomic_load_u64(&counter->accumbytes,
|
||||
ATOMIC_RELAXED);
|
||||
do {
|
||||
a1 = (a0 >= SC_LARGE_MINCLASS - usize)
|
||||
? a0 - (SC_LARGE_MINCLASS - usize) : 0;
|
||||
a1 = (a0 >= bytes) ? a0 - bytes : 0;
|
||||
} while (!atomic_compare_exchange_weak_u64(
|
||||
&counter->accumbytes, &a0, a1, ATOMIC_RELAXED,
|
||||
ATOMIC_RELAXED));
|
||||
#else
|
||||
malloc_mutex_lock(tsdn, &counter->mtx);
|
||||
a0 = counter->accumbytes;
|
||||
a1 = (a0 >= SC_LARGE_MINCLASS - usize)
|
||||
? a0 - (SC_LARGE_MINCLASS - usize) : 0;
|
||||
a1 = (a0 >= bytes) ? a0 - bytes : 0;
|
||||
counter->accumbytes = a1;
|
||||
malloc_mutex_unlock(tsdn, &counter->mtx);
|
||||
#endif
|
||||
|
@@ -22,6 +22,7 @@ typedef enum emitter_type_e emitter_type_t;
|
||||
enum emitter_type_e {
|
||||
emitter_type_bool,
|
||||
emitter_type_int,
|
||||
emitter_type_int64,
|
||||
emitter_type_unsigned,
|
||||
emitter_type_uint32,
|
||||
emitter_type_uint64,
|
||||
@@ -149,6 +150,9 @@ emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width,
|
||||
case emitter_type_int:
|
||||
EMIT_SIMPLE(int, "%d")
|
||||
break;
|
||||
case emitter_type_int64:
|
||||
EMIT_SIMPLE(int64_t, "%" FMTd64)
|
||||
break;
|
||||
case emitter_type_unsigned:
|
||||
EMIT_SIMPLE(unsigned, "%u")
|
||||
break;
|
||||
|
@@ -24,8 +24,26 @@ enum {
|
||||
extern bool opt_stats_print;
|
||||
extern char opt_stats_print_opts[stats_print_tot_num_options+1];
|
||||
|
||||
/* Utilities for stats_interval. */
|
||||
extern int64_t opt_stats_interval;
|
||||
extern char opt_stats_interval_opts[stats_print_tot_num_options+1];
|
||||
|
||||
#define STATS_INTERVAL_DEFAULT -1
|
||||
/*
|
||||
* Batch-increment the counter to reduce synchronization overhead. Each thread
|
||||
* merges after (interval >> LG_BATCH_SIZE) bytes of allocations; also limit the
|
||||
* BATCH_MAX for accuracy when the interval is huge (which is expected).
|
||||
*/
|
||||
#define STATS_INTERVAL_ACCUM_LG_BATCH_SIZE 6
|
||||
#define STATS_INTERVAL_ACCUM_BATCH_MAX (4 << 20)
|
||||
|
||||
uint64_t stats_interval_accum_batch_size(void);
|
||||
bool stats_interval_accum(tsd_t *tsd, uint64_t bytes);
|
||||
|
||||
/* Implements je_malloc_stats_print. */
|
||||
void stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
const char *opts);
|
||||
|
||||
bool stats_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_STATS_H */
|
||||
|
@@ -36,7 +36,8 @@ void tsd_thread_event_init(tsd_t *tsd);
|
||||
*/
|
||||
#define ITERATE_OVER_ALL_EVENTS \
|
||||
E(tcache_gc, (TCACHE_GC_INCR_BYTES > 0)) \
|
||||
E(prof_sample, (config_prof && opt_prof))
|
||||
E(prof_sample, (config_prof && opt_prof)) \
|
||||
E(stats_interval, (opt_stats_interval >= 0))
|
||||
|
||||
#define E(event, condition) \
|
||||
C(event##_event_wait)
|
||||
@@ -46,7 +47,8 @@ void tsd_thread_event_init(tsd_t *tsd);
|
||||
C(thread_allocated) \
|
||||
C(thread_allocated_last_event) \
|
||||
ITERATE_OVER_ALL_EVENTS \
|
||||
C(prof_sample_last_event)
|
||||
C(prof_sample_last_event) \
|
||||
C(stats_interval_last_event)
|
||||
|
||||
/* Getters directly wrap TSD getters. */
|
||||
#define C(counter) \
|
||||
|
@@ -87,6 +87,8 @@ typedef void (*test_callback_t)(int *);
|
||||
O(tcache_gc_event_wait, uint64_t, uint64_t) \
|
||||
O(prof_sample_event_wait, uint64_t, uint64_t) \
|
||||
O(prof_sample_last_event, uint64_t, uint64_t) \
|
||||
O(stats_interval_event_wait, uint64_t, uint64_t) \
|
||||
O(stats_interval_last_event, uint64_t, uint64_t) \
|
||||
O(prof_tdata, prof_tdata_t *, prof_tdata_t *) \
|
||||
O(prng_state, uint64_t, uint64_t) \
|
||||
O(iarena, arena_t *, arena_t *) \
|
||||
@@ -118,6 +120,8 @@ typedef void (*test_callback_t)(int *);
|
||||
/* tcache_gc_event_wait */ THREAD_EVENT_MIN_START_WAIT, \
|
||||
/* prof_sample_event_wait */ THREAD_EVENT_MIN_START_WAIT, \
|
||||
/* prof_sample_last_event */ 0, \
|
||||
/* stats_interval_event_wait */ THREAD_EVENT_MIN_START_WAIT, \
|
||||
/* stats_interval_last_event */ 0, \
|
||||
/* prof_tdata */ NULL, \
|
||||
/* prng_state */ 0, \
|
||||
/* iarena */ NULL, \
|
||||
|
Reference in New Issue
Block a user