2017-04-11 09:17:55 +08:00
|
|
|
#include "jemalloc/internal/jemalloc_preamble.h"
|
|
|
|
#include "jemalloc/internal/jemalloc_internal_includes.h"
|
2010-01-17 01:53:50 +08:00
|
|
|
|
2017-04-12 05:43:12 +08:00
|
|
|
#include "jemalloc/internal/assert.h"
|
2017-04-25 08:09:56 +08:00
|
|
|
#include "jemalloc/internal/ctl.h"
|
2018-03-02 09:29:58 +08:00
|
|
|
#include "jemalloc/internal/emitter.h"
|
2017-05-24 03:28:19 +08:00
|
|
|
#include "jemalloc/internal/mutex.h"
|
2017-04-25 08:09:56 +08:00
|
|
|
#include "jemalloc/internal/mutex_prof.h"
|
2020-08-14 07:47:40 +08:00
|
|
|
#include "jemalloc/internal/prof_stats.h"
|
2017-04-12 05:43:12 +08:00
|
|
|
|
2017-04-25 08:09:56 +08:00
|
|
|
const char *global_mutex_names[mutex_prof_num_global_mutexes] = {
|
2017-03-22 02:56:38 +08:00
|
|
|
#define OP(mtx) #mtx,
|
2017-04-25 08:09:56 +08:00
|
|
|
MUTEX_PROF_GLOBAL_MUTEXES
|
2017-03-22 02:56:38 +08:00
|
|
|
#undef OP
|
|
|
|
};
|
|
|
|
|
2017-04-25 08:09:56 +08:00
|
|
|
const char *arena_mutex_names[mutex_prof_num_arena_mutexes] = {
|
2017-03-22 02:56:38 +08:00
|
|
|
#define OP(mtx) #mtx,
|
2017-04-25 08:09:56 +08:00
|
|
|
MUTEX_PROF_ARENA_MUTEXES
|
2017-03-22 02:56:38 +08:00
|
|
|
#undef OP
|
|
|
|
};
|
|
|
|
|
2017-01-20 13:41:41 +08:00
|
|
|
#define CTL_GET(n, v, t) do { \
|
2010-01-28 05:10:55 +08:00
|
|
|
size_t sz = sizeof(t); \
|
2016-10-28 12:31:25 +08:00
|
|
|
xmallctl(n, (void *)v, &sz, NULL, 0); \
|
2010-01-28 05:10:55 +08:00
|
|
|
} while (0)
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
#define CTL_LEAF_PREPARE(mib, miblen, name) do { \
|
|
|
|
assert(miblen < CTL_MAX_DEPTH); \
|
|
|
|
size_t miblen_new = CTL_MAX_DEPTH; \
|
|
|
|
xmallctlmibnametomib(mib, miblen, name, &miblen_new); \
|
|
|
|
assert(miblen_new > miblen); \
|
2010-01-28 05:10:55 +08:00
|
|
|
} while (0)
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
#define CTL_LEAF(mib, miblen, leaf, v, t) do { \
|
|
|
|
assert(miblen < CTL_MAX_DEPTH); \
|
|
|
|
size_t miblen_new = CTL_MAX_DEPTH; \
|
2010-01-28 05:10:55 +08:00
|
|
|
size_t sz = sizeof(t); \
|
2020-12-18 06:01:56 +08:00
|
|
|
xmallctlbymibname(mib, miblen, leaf, &miblen_new, (void *)v, \
|
|
|
|
&sz, NULL, 0); \
|
|
|
|
assert(miblen_new == miblen + 1); \
|
2010-01-28 05:10:55 +08:00
|
|
|
} while (0)
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
#define CTL_M2_GET(n, i, v, t) do { \
|
2020-09-05 03:01:52 +08:00
|
|
|
size_t mib[CTL_MAX_DEPTH]; \
|
|
|
|
size_t miblen = sizeof(mib) / sizeof(size_t); \
|
|
|
|
size_t sz = sizeof(t); \
|
|
|
|
xmallctlnametomib(n, mib, &miblen); \
|
|
|
|
mib[2] = (i); \
|
|
|
|
xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \
|
|
|
|
} while (0)
|
|
|
|
|
2010-01-17 01:53:50 +08:00
|
|
|
/******************************************************************************/
|
|
|
|
/* Data. */
|
|
|
|
|
2017-05-28 06:35:36 +08:00
|
|
|
bool opt_stats_print = false;
|
|
|
|
char opt_stats_print_opts[stats_print_tot_num_options+1] = "";
|
2010-01-17 01:53:50 +08:00
|
|
|
|
2020-01-14 14:29:17 +08:00
|
|
|
int64_t opt_stats_interval = STATS_INTERVAL_DEFAULT;
|
|
|
|
char opt_stats_interval_opts[stats_print_tot_num_options+1] = "";
|
|
|
|
|
|
|
|
static counter_accum_t stats_interval_accumulated;
|
|
|
|
/* Per thread batch accum size for stats_interval. */
|
|
|
|
static uint64_t stats_interval_accum_batch;
|
|
|
|
|
2010-01-17 01:53:50 +08:00
|
|
|
/******************************************************************************/
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
static uint64_t
|
|
|
|
rate_per_second(uint64_t value, uint64_t uptime_ns) {
|
|
|
|
uint64_t billion = 1000000000;
|
|
|
|
if (uptime_ns == 0 || value == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (uptime_ns < billion) {
|
|
|
|
return value;
|
|
|
|
} else {
|
|
|
|
uint64_t uptime_s = uptime_ns / billion;
|
|
|
|
return value / uptime_s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-04 11:58:43 +08:00
|
|
|
/* Calculate x.yyy and output a string (takes a fixed sized char array). */
|
|
|
|
static bool
|
|
|
|
get_rate_str(uint64_t dividend, uint64_t divisor, char str[6]) {
|
|
|
|
if (divisor == 0 || dividend > divisor) {
|
|
|
|
/* The rate is not supposed to be greater than 1. */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (dividend > 0) {
|
|
|
|
assert(UINT64_MAX / dividend >= 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned n = (unsigned)((dividend * 1000) / divisor);
|
|
|
|
if (n < 10) {
|
|
|
|
malloc_snprintf(str, 6, "0.00%u", n);
|
|
|
|
} else if (n < 100) {
|
|
|
|
malloc_snprintf(str, 6, "0.0%u", n);
|
|
|
|
} else if (n < 1000) {
|
|
|
|
malloc_snprintf(str, 6, "0.%u", n);
|
|
|
|
} else {
|
|
|
|
malloc_snprintf(str, 6, "1");
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-03-12 17:28:52 +08:00
|
|
|
static void
|
2018-03-07 10:50:53 +08:00
|
|
|
mutex_stats_init_cols(emitter_row_t *row, const char *table_name,
|
2018-03-03 07:15:19 +08:00
|
|
|
emitter_col_t *name,
|
|
|
|
emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters],
|
|
|
|
emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters]) {
|
|
|
|
mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0;
|
|
|
|
mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0;
|
|
|
|
|
|
|
|
emitter_col_t *col;
|
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
if (name != NULL) {
|
|
|
|
emitter_col_init(name, row);
|
|
|
|
name->justify = emitter_justify_left;
|
|
|
|
name->width = 21;
|
|
|
|
name->type = emitter_type_title;
|
|
|
|
name->str_val = table_name;
|
|
|
|
}
|
2018-03-03 07:15:19 +08:00
|
|
|
|
|
|
|
#define WIDTH_uint32_t 12
|
|
|
|
#define WIDTH_uint64_t 16
|
2019-10-18 07:46:45 +08:00
|
|
|
#define OP(counter, counter_type, human, derived, base_counter) \
|
2018-03-03 07:15:19 +08:00
|
|
|
col = &col_##counter_type[k_##counter_type]; \
|
|
|
|
++k_##counter_type; \
|
|
|
|
emitter_col_init(col, row); \
|
|
|
|
col->justify = emitter_justify_right; \
|
2018-12-11 03:29:44 +08:00
|
|
|
col->width = derived ? 8 : WIDTH_##counter_type; \
|
2018-03-03 07:15:19 +08:00
|
|
|
col->type = emitter_type_title; \
|
|
|
|
col->str_val = human;
|
|
|
|
MUTEX_PROF_COUNTERS
|
|
|
|
#undef OP
|
|
|
|
#undef WIDTH_uint32_t
|
|
|
|
#undef WIDTH_uint64_t
|
2019-01-29 06:05:20 +08:00
|
|
|
col_uint64_t[mutex_counter_total_wait_time_ps].width = 10;
|
2018-03-03 07:15:19 +08:00
|
|
|
}
|
|
|
|
|
2018-03-06 10:46:44 +08:00
|
|
|
static void
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_global(size_t mib[], size_t miblen, const char *name,
|
|
|
|
emitter_col_t *col_name,
|
2018-03-06 10:46:44 +08:00
|
|
|
emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters],
|
2018-12-11 03:29:44 +08:00
|
|
|
emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters],
|
|
|
|
uint64_t uptime) {
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF_PREPARE(mib, miblen, name);
|
|
|
|
size_t miblen_name = miblen + 1;
|
2018-03-06 10:46:44 +08:00
|
|
|
|
|
|
|
col_name->str_val = name;
|
|
|
|
|
|
|
|
emitter_col_t *dst;
|
|
|
|
#define EMITTER_TYPE_uint32_t emitter_type_uint32
|
|
|
|
#define EMITTER_TYPE_uint64_t emitter_type_uint64
|
2019-10-18 07:46:45 +08:00
|
|
|
#define OP(counter, counter_type, human, derived, base_counter) \
|
2018-03-06 10:46:44 +08:00
|
|
|
dst = &col_##counter_type[mutex_counter_##counter]; \
|
|
|
|
dst->type = EMITTER_TYPE_##counter_type; \
|
2018-12-11 03:29:44 +08:00
|
|
|
if (!derived) { \
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(mib, miblen_name, #counter, \
|
|
|
|
(counter_type *)&dst->bool_val, counter_type); \
|
2019-10-18 07:46:45 +08:00
|
|
|
} else { \
|
|
|
|
emitter_col_t *base = \
|
|
|
|
&col_##counter_type[mutex_counter_##base_counter]; \
|
|
|
|
dst->counter_type##_val = \
|
|
|
|
(counter_type)rate_per_second( \
|
|
|
|
base->counter_type##_val, uptime); \
|
2018-12-11 03:29:44 +08:00
|
|
|
}
|
2018-03-06 10:46:44 +08:00
|
|
|
MUTEX_PROF_COUNTERS
|
|
|
|
#undef OP
|
|
|
|
#undef EMITTER_TYPE_uint32_t
|
|
|
|
#undef EMITTER_TYPE_uint64_t
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_arena(size_t mib[], size_t miblen, const char *name,
|
|
|
|
emitter_col_t *col_name,
|
2018-03-06 10:46:44 +08:00
|
|
|
emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters],
|
2018-12-11 03:29:44 +08:00
|
|
|
emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters],
|
|
|
|
uint64_t uptime) {
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF_PREPARE(mib, miblen, name);
|
|
|
|
size_t miblen_name = miblen + 1;
|
2018-03-06 10:46:44 +08:00
|
|
|
|
|
|
|
col_name->str_val = name;
|
|
|
|
|
|
|
|
emitter_col_t *dst;
|
|
|
|
#define EMITTER_TYPE_uint32_t emitter_type_uint32
|
|
|
|
#define EMITTER_TYPE_uint64_t emitter_type_uint64
|
2019-10-18 07:46:45 +08:00
|
|
|
#define OP(counter, counter_type, human, derived, base_counter) \
|
2018-03-06 10:46:44 +08:00
|
|
|
dst = &col_##counter_type[mutex_counter_##counter]; \
|
|
|
|
dst->type = EMITTER_TYPE_##counter_type; \
|
2019-10-18 07:46:45 +08:00
|
|
|
if (!derived) { \
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(mib, miblen_name, #counter, \
|
2019-10-18 07:46:45 +08:00
|
|
|
(counter_type *)&dst->bool_val, counter_type); \
|
|
|
|
} else { \
|
|
|
|
emitter_col_t *base = \
|
|
|
|
&col_##counter_type[mutex_counter_##base_counter]; \
|
|
|
|
dst->counter_type##_val = \
|
|
|
|
(counter_type)rate_per_second( \
|
|
|
|
base->counter_type##_val, uptime); \
|
2018-12-11 03:29:44 +08:00
|
|
|
}
|
2018-03-06 10:46:44 +08:00
|
|
|
MUTEX_PROF_COUNTERS
|
|
|
|
#undef OP
|
2018-03-07 10:50:53 +08:00
|
|
|
#undef EMITTER_TYPE_uint32_t
|
|
|
|
#undef EMITTER_TYPE_uint64_t
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_arena_bin(size_t mib[], size_t miblen,
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters],
|
2018-12-11 03:29:44 +08:00
|
|
|
emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters],
|
|
|
|
uint64_t uptime) {
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF_PREPARE(mib, miblen, "mutex");
|
|
|
|
size_t miblen_mutex = miblen + 1;
|
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_col_t *dst;
|
|
|
|
|
|
|
|
#define EMITTER_TYPE_uint32_t emitter_type_uint32
|
|
|
|
#define EMITTER_TYPE_uint64_t emitter_type_uint64
|
2019-10-18 07:46:45 +08:00
|
|
|
#define OP(counter, counter_type, human, derived, base_counter) \
|
2018-03-07 10:50:53 +08:00
|
|
|
dst = &col_##counter_type[mutex_counter_##counter]; \
|
|
|
|
dst->type = EMITTER_TYPE_##counter_type; \
|
2019-10-18 07:46:45 +08:00
|
|
|
if (!derived) { \
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(mib, miblen_mutex, #counter, \
|
2019-10-18 07:46:45 +08:00
|
|
|
(counter_type *)&dst->bool_val, counter_type); \
|
|
|
|
} else { \
|
|
|
|
emitter_col_t *base = \
|
|
|
|
&col_##counter_type[mutex_counter_##base_counter]; \
|
|
|
|
dst->counter_type##_val = \
|
|
|
|
(counter_type)rate_per_second( \
|
|
|
|
base->counter_type##_val, uptime); \
|
2018-12-11 03:29:44 +08:00
|
|
|
}
|
2018-03-07 10:50:53 +08:00
|
|
|
MUTEX_PROF_COUNTERS
|
|
|
|
#undef OP
|
|
|
|
#undef EMITTER_TYPE_uint32_t
|
|
|
|
#undef EMITTER_TYPE_uint64_t
|
2018-03-06 10:46:44 +08:00
|
|
|
}
|
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
/* "row" can be NULL to avoid emitting in table mode. */
|
2018-03-03 07:15:19 +08:00
|
|
|
static void
|
|
|
|
mutex_stats_emit(emitter_t *emitter, emitter_row_t *row,
|
|
|
|
emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters],
|
|
|
|
emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters]) {
|
2018-03-07 10:50:53 +08:00
|
|
|
if (row != NULL) {
|
|
|
|
emitter_table_row(emitter, row);
|
|
|
|
}
|
2018-03-03 07:15:19 +08:00
|
|
|
|
|
|
|
mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0;
|
|
|
|
mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0;
|
|
|
|
|
|
|
|
emitter_col_t *col;
|
|
|
|
|
|
|
|
#define EMITTER_TYPE_uint32_t emitter_type_uint32
|
|
|
|
#define EMITTER_TYPE_uint64_t emitter_type_uint64
|
2018-12-11 03:29:44 +08:00
|
|
|
#define OP(counter, type, human, derived, base_counter) \
|
|
|
|
if (!derived) { \
|
|
|
|
col = &col_##type[k_##type]; \
|
|
|
|
++k_##type; \
|
|
|
|
emitter_json_kv(emitter, #counter, EMITTER_TYPE_##type, \
|
|
|
|
(const void *)&col->bool_val); \
|
|
|
|
}
|
2018-03-03 07:15:19 +08:00
|
|
|
MUTEX_PROF_COUNTERS;
|
|
|
|
#undef OP
|
|
|
|
#undef EMITTER_TYPE_uint32_t
|
|
|
|
#undef EMITTER_TYPE_uint64_t
|
|
|
|
}
|
|
|
|
|
2020-08-18 01:40:28 +08:00
|
|
|
#define COL_DECLARE(column_name) \
|
|
|
|
emitter_col_t col_##column_name;
|
|
|
|
|
|
|
|
#define COL_INIT(row_name, column_name, left_or_right, col_width, etype)\
|
|
|
|
emitter_col_init(&col_##column_name, &row_name); \
|
|
|
|
col_##column_name.justify = emitter_justify_##left_or_right; \
|
|
|
|
col_##column_name.width = col_width; \
|
2018-12-11 03:29:44 +08:00
|
|
|
col_##column_name.type = emitter_type_##etype;
|
|
|
|
|
2020-08-18 01:40:28 +08:00
|
|
|
#define COL(row_name, column_name, left_or_right, col_width, etype) \
|
|
|
|
COL_DECLARE(column_name); \
|
|
|
|
COL_INIT(row_name, column_name, left_or_right, col_width, etype)
|
|
|
|
|
|
|
|
#define COL_HDR_DECLARE(column_name) \
|
|
|
|
COL_DECLARE(column_name); \
|
|
|
|
emitter_col_t header_##column_name;
|
|
|
|
|
|
|
|
#define COL_HDR_INIT(row_name, column_name, human, left_or_right, \
|
|
|
|
col_width, etype) \
|
|
|
|
COL_INIT(row_name, column_name, left_or_right, col_width, etype)\
|
|
|
|
emitter_col_init(&header_##column_name, &header_##row_name); \
|
|
|
|
header_##column_name.justify = emitter_justify_##left_or_right; \
|
|
|
|
header_##column_name.width = col_width; \
|
|
|
|
header_##column_name.type = emitter_type_title; \
|
2018-12-11 03:29:44 +08:00
|
|
|
header_##column_name.str_val = human ? human : #column_name;
|
|
|
|
|
2020-08-18 01:40:28 +08:00
|
|
|
#define COL_HDR(row_name, column_name, human, left_or_right, col_width, \
|
|
|
|
etype) \
|
|
|
|
COL_HDR_DECLARE(column_name) \
|
|
|
|
COL_HDR_INIT(row_name, column_name, human, left_or_right, \
|
|
|
|
col_width, etype)
|
2018-12-11 03:29:44 +08:00
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2017-03-22 02:56:38 +08:00
|
|
|
static void
|
2020-08-14 07:47:40 +08:00
|
|
|
stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i,
|
|
|
|
uint64_t uptime) {
|
2012-04-02 22:15:42 +08:00
|
|
|
size_t page;
|
2017-01-18 17:01:19 +08:00
|
|
|
bool in_gap, in_gap_prev;
|
2014-10-13 13:53:59 +08:00
|
|
|
unsigned nbins, j;
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2012-04-02 22:15:42 +08:00
|
|
|
CTL_GET("arenas.page", &page, size_t);
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("arenas.nbins", &nbins, unsigned);
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
emitter_row_t header_row;
|
|
|
|
emitter_row_init(&header_row);
|
|
|
|
|
|
|
|
emitter_row_t row;
|
|
|
|
emitter_row_init(&row);
|
2018-12-11 03:29:44 +08:00
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
bool prof_stats_on = config_prof && opt_prof && opt_prof_stats
|
|
|
|
&& i == MALLCTL_ARENAS_ALL;
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, size, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, ind, NULL, right, 4, unsigned)
|
|
|
|
COL_HDR(row, allocated, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nmalloc, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nmalloc_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, ndalloc, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, ndalloc_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, nrequests, NULL, right, 13, uint64)
|
2019-01-19 07:51:01 +08:00
|
|
|
COL_HDR(row, nrequests_ps, "(#/sec)", right, 10, uint64)
|
2020-08-14 07:47:40 +08:00
|
|
|
COL_HDR_DECLARE(prof_live_requested);
|
|
|
|
COL_HDR_DECLARE(prof_live_count);
|
|
|
|
COL_HDR_DECLARE(prof_accum_requested);
|
|
|
|
COL_HDR_DECLARE(prof_accum_count);
|
|
|
|
if (prof_stats_on) {
|
|
|
|
COL_HDR_INIT(row, prof_live_requested, NULL, right, 21, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_live_count, NULL, right, 17, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_accum_requested, NULL, right, 21, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_accum_count, NULL, right, 17, uint64)
|
|
|
|
}
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, nshards, NULL, right, 9, unsigned)
|
|
|
|
COL_HDR(row, curregs, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, curslabs, NULL, right, 13, size)
|
2019-04-12 19:08:50 +08:00
|
|
|
COL_HDR(row, nonfull_slabs, NULL, right, 15, size)
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, regs, NULL, right, 5, unsigned)
|
|
|
|
COL_HDR(row, pgs, NULL, right, 4, size)
|
2018-03-07 10:50:53 +08:00
|
|
|
/* To buffer a right- and left-justified column. */
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, justify_spacer, NULL, right, 1, title)
|
|
|
|
COL_HDR(row, util, NULL, right, 6, title)
|
|
|
|
COL_HDR(row, nfills, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nfills_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, nflushes, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nflushes_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, nslabs, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nreslabs, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nreslabs_ps, "(#/sec)", right, 8, uint64)
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
/* Don't want to actually print the name. */
|
2018-12-11 03:29:44 +08:00
|
|
|
header_justify_spacer.str_val = " ";
|
2018-03-07 10:50:53 +08:00
|
|
|
col_justify_spacer.str_val = " ";
|
|
|
|
|
|
|
|
emitter_col_t col_mutex64[mutex_prof_num_uint64_t_counters];
|
|
|
|
emitter_col_t col_mutex32[mutex_prof_num_uint32_t_counters];
|
|
|
|
|
|
|
|
emitter_col_t header_mutex64[mutex_prof_num_uint64_t_counters];
|
|
|
|
emitter_col_t header_mutex32[mutex_prof_num_uint32_t_counters];
|
|
|
|
|
|
|
|
if (mutex) {
|
|
|
|
mutex_stats_init_cols(&row, NULL, NULL, col_mutex64,
|
|
|
|
col_mutex32);
|
|
|
|
mutex_stats_init_cols(&header_row, NULL, NULL, header_mutex64,
|
|
|
|
header_mutex32);
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We print a "bins:" header as part of the table row; we need to adjust
|
|
|
|
* the header size column to compensate.
|
|
|
|
*/
|
2018-12-11 03:29:44 +08:00
|
|
|
header_size.width -=5;
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_table_printf(emitter, "bins:");
|
|
|
|
emitter_table_row(emitter, &header_row);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_kv_begin(emitter, "bins");
|
2018-03-07 10:50:53 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_arenas_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 0, "stats.arenas");
|
|
|
|
stats_arenas_mib[2] = i;
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 3, "bins");
|
|
|
|
|
|
|
|
size_t arenas_bin_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(arenas_bin_mib, 0, "arenas.bin");
|
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
size_t prof_stats_mib[CTL_MAX_DEPTH];
|
|
|
|
if (prof_stats_on) {
|
|
|
|
CTL_LEAF_PREPARE(prof_stats_mib, 0, "prof.stats.bins");
|
|
|
|
}
|
|
|
|
|
2014-10-13 13:53:59 +08:00
|
|
|
for (j = 0, in_gap = false; j < nbins; j++) {
|
2016-05-30 09:34:50 +08:00
|
|
|
uint64_t nslabs;
|
2016-11-01 13:30:49 +08:00
|
|
|
size_t reg_size, slab_size, curregs;
|
|
|
|
size_t curslabs;
|
2019-04-12 19:08:50 +08:00
|
|
|
size_t nonfull_slabs;
|
2018-11-22 03:17:31 +08:00
|
|
|
uint32_t nregs, nshards;
|
2016-11-01 13:30:49 +08:00
|
|
|
uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
|
|
|
|
uint64_t nreslabs;
|
2020-08-14 07:47:40 +08:00
|
|
|
prof_stats_t prof_live;
|
|
|
|
prof_stats_t prof_accum;
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
stats_arenas_mib[4] = j;
|
|
|
|
arenas_bin_mib[2] = j;
|
|
|
|
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nslabs", &nslabs, uint64_t);
|
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
prof_stats_mib[3] = j;
|
|
|
|
CTL_LEAF(prof_stats_mib, 4, "live", &prof_live,
|
|
|
|
prof_stats_t);
|
|
|
|
CTL_LEAF(prof_stats_mib, 4, "accum", &prof_accum,
|
|
|
|
prof_stats_t);
|
|
|
|
}
|
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
in_gap_prev = in_gap;
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
in_gap = (nslabs == 0 && prof_accum.count == 0);
|
|
|
|
} else {
|
|
|
|
in_gap = (nslabs == 0);
|
|
|
|
}
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
if (in_gap_prev && !in_gap) {
|
|
|
|
emitter_table_printf(emitter,
|
2016-11-01 13:30:49 +08:00
|
|
|
" ---\n");
|
|
|
|
}
|
|
|
|
|
2020-08-25 06:15:27 +08:00
|
|
|
if (in_gap && !emitter_outputs_json(emitter)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "size", ®_size, size_t);
|
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "nregs", &nregs, uint32_t);
|
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "slab_size", &slab_size, size_t);
|
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "nshards", &nshards, uint32_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nmalloc", &nmalloc, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "ndalloc", &ndalloc, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "curregs", &curregs, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nrequests", &nrequests,
|
2016-11-01 13:30:49 +08:00
|
|
|
uint64_t);
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nfills", &nfills, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nflushes", &nflushes, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nreslabs", &nreslabs, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "curslabs", &curslabs, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nonfull_slabs", &nonfull_slabs,
|
2019-04-12 19:08:50 +08:00
|
|
|
size_t);
|
2017-03-11 04:14:05 +08:00
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
if (mutex) {
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_arena_bin(stats_arenas_mib, 5,
|
|
|
|
col_mutex64, col_mutex32, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
}
|
2017-03-12 17:28:52 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_begin(emitter);
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_json_kv(emitter, "nmalloc", emitter_type_uint64,
|
|
|
|
&nmalloc);
|
|
|
|
emitter_json_kv(emitter, "ndalloc", emitter_type_uint64,
|
|
|
|
&ndalloc);
|
|
|
|
emitter_json_kv(emitter, "curregs", emitter_type_size,
|
|
|
|
&curregs);
|
|
|
|
emitter_json_kv(emitter, "nrequests", emitter_type_uint64,
|
|
|
|
&nrequests);
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
emitter_json_kv(emitter, "prof_live_requested",
|
|
|
|
emitter_type_uint64, &prof_live.req_sum);
|
|
|
|
emitter_json_kv(emitter, "prof_live_count",
|
|
|
|
emitter_type_uint64, &prof_live.count);
|
|
|
|
emitter_json_kv(emitter, "prof_accum_requested",
|
|
|
|
emitter_type_uint64, &prof_accum.req_sum);
|
|
|
|
emitter_json_kv(emitter, "prof_accum_count",
|
|
|
|
emitter_type_uint64, &prof_accum.count);
|
|
|
|
}
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_json_kv(emitter, "nfills", emitter_type_uint64,
|
|
|
|
&nfills);
|
|
|
|
emitter_json_kv(emitter, "nflushes", emitter_type_uint64,
|
|
|
|
&nflushes);
|
|
|
|
emitter_json_kv(emitter, "nreslabs", emitter_type_uint64,
|
|
|
|
&nreslabs);
|
|
|
|
emitter_json_kv(emitter, "curslabs", emitter_type_size,
|
|
|
|
&curslabs);
|
2019-04-12 19:08:50 +08:00
|
|
|
emitter_json_kv(emitter, "nonfull_slabs", emitter_type_size,
|
|
|
|
&nonfull_slabs);
|
2018-03-07 10:50:53 +08:00
|
|
|
if (mutex) {
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "mutex");
|
2018-03-07 10:50:53 +08:00
|
|
|
mutex_stats_emit(emitter, NULL, col_mutex64,
|
|
|
|
col_mutex32);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2018-03-07 10:50:53 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
size_t availregs = nregs * curslabs;
|
|
|
|
char util[6];
|
|
|
|
if (get_rate_str((uint64_t)curregs, (uint64_t)availregs, util))
|
|
|
|
{
|
|
|
|
if (availregs == 0) {
|
|
|
|
malloc_snprintf(util, sizeof(util), "1");
|
|
|
|
} else if (curregs > availregs) {
|
|
|
|
/*
|
|
|
|
* Race detected: the counters were read in
|
|
|
|
* separate mallctl calls and concurrent
|
|
|
|
* operations happened in between. In this case
|
|
|
|
* no meaningful utilization can be computed.
|
|
|
|
*/
|
|
|
|
malloc_snprintf(util, sizeof(util), " race");
|
2017-04-19 06:00:14 +08:00
|
|
|
} else {
|
2018-03-07 10:50:53 +08:00
|
|
|
not_reached();
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
|
|
|
}
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
col_size.size_val = reg_size;
|
|
|
|
col_ind.unsigned_val = j;
|
|
|
|
col_allocated.size_val = curregs * reg_size;
|
|
|
|
col_nmalloc.uint64_val = nmalloc;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nmalloc_ps.uint64_val = rate_per_second(nmalloc, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
col_ndalloc.uint64_val = ndalloc;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_ndalloc_ps.uint64_val = rate_per_second(ndalloc, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
col_nrequests.uint64_val = nrequests;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nrequests_ps.uint64_val = rate_per_second(nrequests, uptime);
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
col_prof_live_requested.uint64_val = prof_live.req_sum;
|
|
|
|
col_prof_live_count.uint64_val = prof_live.count;
|
|
|
|
col_prof_accum_requested.uint64_val =
|
|
|
|
prof_accum.req_sum;
|
|
|
|
col_prof_accum_count.uint64_val = prof_accum.count;
|
|
|
|
}
|
2018-11-22 03:17:31 +08:00
|
|
|
col_nshards.unsigned_val = nshards;
|
2018-03-07 10:50:53 +08:00
|
|
|
col_curregs.size_val = curregs;
|
|
|
|
col_curslabs.size_val = curslabs;
|
2019-04-12 19:08:50 +08:00
|
|
|
col_nonfull_slabs.size_val = nonfull_slabs;
|
2018-03-07 10:50:53 +08:00
|
|
|
col_regs.unsigned_val = nregs;
|
|
|
|
col_pgs.size_val = slab_size / page;
|
|
|
|
col_util.str_val = util;
|
|
|
|
col_nfills.uint64_val = nfills;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nfills_ps.uint64_val = rate_per_second(nfills, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
col_nflushes.uint64_val = nflushes;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nflushes_ps.uint64_val = rate_per_second(nflushes, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
col_nslabs.uint64_val = nslabs;
|
|
|
|
col_nreslabs.uint64_val = nreslabs;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nreslabs_ps.uint64_val = rate_per_second(nreslabs, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that mutex columns were initialized above, if mutex ==
|
|
|
|
* true.
|
|
|
|
*/
|
|
|
|
|
|
|
|
emitter_table_row(emitter, &row);
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_end(emitter); /* Close "bins". */
|
2018-03-07 10:50:53 +08:00
|
|
|
|
|
|
|
if (in_gap) {
|
|
|
|
emitter_table_printf(emitter, " ---\n");
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2014-10-13 13:53:59 +08:00
|
|
|
static void
|
2018-12-11 03:29:44 +08:00
|
|
|
stats_arena_lextents_print(emitter_t *emitter, unsigned i, uint64_t uptime) {
|
2016-06-01 05:50:21 +08:00
|
|
|
unsigned nbins, nlextents, j;
|
2016-11-01 13:30:49 +08:00
|
|
|
bool in_gap, in_gap_prev;
|
2014-10-13 13:53:59 +08:00
|
|
|
|
|
|
|
CTL_GET("arenas.nbins", &nbins, unsigned);
|
2016-06-01 05:50:21 +08:00
|
|
|
CTL_GET("arenas.nlextents", &nlextents, unsigned);
|
2018-03-07 12:25:35 +08:00
|
|
|
|
|
|
|
emitter_row_t header_row;
|
|
|
|
emitter_row_init(&header_row);
|
|
|
|
emitter_row_t row;
|
|
|
|
emitter_row_init(&row);
|
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
bool prof_stats_on = config_prof && opt_prof && opt_prof_stats
|
|
|
|
&& i == MALLCTL_ARENAS_ALL;
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, size, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, ind, NULL, right, 4, unsigned)
|
|
|
|
COL_HDR(row, allocated, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, nmalloc, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nmalloc_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, ndalloc, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, ndalloc_ps, "(#/sec)", right, 8, uint64)
|
|
|
|
COL_HDR(row, nrequests, NULL, right, 13, uint64)
|
|
|
|
COL_HDR(row, nrequests_ps, "(#/sec)", right, 8, uint64)
|
2020-08-14 07:47:40 +08:00
|
|
|
COL_HDR_DECLARE(prof_live_requested)
|
|
|
|
COL_HDR_DECLARE(prof_live_count)
|
|
|
|
COL_HDR_DECLARE(prof_accum_requested)
|
|
|
|
COL_HDR_DECLARE(prof_accum_count)
|
|
|
|
if (prof_stats_on) {
|
|
|
|
COL_HDR_INIT(row, prof_live_requested, NULL, right, 21, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_live_count, NULL, right, 17, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_accum_requested, NULL, right, 21, uint64)
|
|
|
|
COL_HDR_INIT(row, prof_accum_count, NULL, right, 17, uint64)
|
|
|
|
}
|
2018-12-11 03:29:44 +08:00
|
|
|
COL_HDR(row, curlextents, NULL, right, 13, size)
|
2018-03-07 12:25:35 +08:00
|
|
|
|
|
|
|
/* As with bins, we label the large extents table. */
|
|
|
|
header_size.width -= 6;
|
|
|
|
emitter_table_printf(emitter, "large:");
|
|
|
|
emitter_table_row(emitter, &header_row);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_kv_begin(emitter, "lextents");
|
2018-03-07 12:25:35 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_arenas_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 0, "stats.arenas");
|
|
|
|
stats_arenas_mib[2] = i;
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 3, "lextents");
|
|
|
|
|
|
|
|
size_t arenas_lextent_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(arenas_lextent_mib, 0, "arenas.lextent");
|
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
size_t prof_stats_mib[CTL_MAX_DEPTH];
|
|
|
|
if (prof_stats_on) {
|
|
|
|
CTL_LEAF_PREPARE(prof_stats_mib, 0, "prof.stats.lextents");
|
|
|
|
}
|
|
|
|
|
2016-06-01 05:50:21 +08:00
|
|
|
for (j = 0, in_gap = false; j < nlextents; j++) {
|
2014-10-13 13:53:59 +08:00
|
|
|
uint64_t nmalloc, ndalloc, nrequests;
|
2016-06-01 05:50:21 +08:00
|
|
|
size_t lextent_size, curlextents;
|
2020-08-14 07:47:40 +08:00
|
|
|
prof_stats_t prof_live;
|
|
|
|
prof_stats_t prof_accum;
|
2014-10-13 13:53:59 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
stats_arenas_mib[4] = j;
|
|
|
|
arenas_lextent_mib[2] = j;
|
|
|
|
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nmalloc", &nmalloc, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "ndalloc", &ndalloc, uint64_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nrequests", &nrequests,
|
|
|
|
uint64_t);
|
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
in_gap_prev = in_gap;
|
2016-11-02 06:26:35 +08:00
|
|
|
in_gap = (nrequests == 0);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-07 12:25:35 +08:00
|
|
|
if (in_gap_prev && !in_gap) {
|
|
|
|
emitter_table_printf(emitter,
|
2016-11-01 13:30:49 +08:00
|
|
|
" ---\n");
|
|
|
|
}
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_lextent_mib, 3, "size", &lextent_size, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "curlextents", &curlextents,
|
|
|
|
size_t);
|
2018-03-07 12:25:35 +08:00
|
|
|
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
prof_stats_mib[3] = j;
|
|
|
|
CTL_LEAF(prof_stats_mib, 4, "live", &prof_live,
|
|
|
|
prof_stats_t);
|
|
|
|
CTL_LEAF(prof_stats_mib, 4, "accum", &prof_accum,
|
|
|
|
prof_stats_t);
|
|
|
|
}
|
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_begin(emitter);
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
emitter_json_kv(emitter, "prof_live_requested",
|
|
|
|
emitter_type_uint64, &prof_live.req_sum);
|
|
|
|
emitter_json_kv(emitter, "prof_live_count",
|
|
|
|
emitter_type_uint64, &prof_live.count);
|
|
|
|
emitter_json_kv(emitter, "prof_accum_requested",
|
|
|
|
emitter_type_uint64, &prof_accum.req_sum);
|
|
|
|
emitter_json_kv(emitter, "prof_accum_count",
|
|
|
|
emitter_type_uint64, &prof_accum.count);
|
|
|
|
}
|
2018-03-07 12:25:35 +08:00
|
|
|
emitter_json_kv(emitter, "curlextents", emitter_type_size,
|
|
|
|
&curlextents);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2018-03-07 12:25:35 +08:00
|
|
|
|
|
|
|
col_size.size_val = lextent_size;
|
|
|
|
col_ind.unsigned_val = nbins + j;
|
|
|
|
col_allocated.size_val = curlextents * lextent_size;
|
|
|
|
col_nmalloc.uint64_val = nmalloc;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nmalloc_ps.uint64_val = rate_per_second(nmalloc, uptime);
|
2018-03-07 12:25:35 +08:00
|
|
|
col_ndalloc.uint64_val = ndalloc;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_ndalloc_ps.uint64_val = rate_per_second(ndalloc, uptime);
|
2018-03-07 12:25:35 +08:00
|
|
|
col_nrequests.uint64_val = nrequests;
|
2018-12-11 03:29:44 +08:00
|
|
|
col_nrequests_ps.uint64_val = rate_per_second(nrequests, uptime);
|
2020-08-14 07:47:40 +08:00
|
|
|
if (prof_stats_on) {
|
|
|
|
col_prof_live_requested.uint64_val = prof_live.req_sum;
|
|
|
|
col_prof_live_count.uint64_val = prof_live.count;
|
|
|
|
col_prof_accum_requested.uint64_val =
|
|
|
|
prof_accum.req_sum;
|
|
|
|
col_prof_accum_count.uint64_val = prof_accum.count;
|
|
|
|
}
|
2018-03-07 12:25:35 +08:00
|
|
|
col_curlextents.size_val = curlextents;
|
|
|
|
|
|
|
|
if (!in_gap) {
|
|
|
|
emitter_table_row(emitter, &row);
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_end(emitter); /* Close "lextents". */
|
2018-03-07 12:25:35 +08:00
|
|
|
if (in_gap) {
|
|
|
|
emitter_table_printf(emitter, " ---\n");
|
2014-10-13 13:53:59 +08:00
|
|
|
}
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2018-08-01 00:49:49 +08:00
|
|
|
static void
|
|
|
|
stats_arena_extents_print(emitter_t *emitter, unsigned i) {
|
|
|
|
unsigned j;
|
|
|
|
bool in_gap, in_gap_prev;
|
|
|
|
emitter_row_t header_row;
|
|
|
|
emitter_row_init(&header_row);
|
|
|
|
emitter_row_t row;
|
|
|
|
emitter_row_init(&row);
|
2018-12-11 03:29:44 +08:00
|
|
|
|
|
|
|
COL_HDR(row, size, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, ind, NULL, right, 4, unsigned)
|
|
|
|
COL_HDR(row, ndirty, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, dirty, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, nmuzzy, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, muzzy, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, nretained, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, retained, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, ntotal, NULL, right, 13, size)
|
|
|
|
COL_HDR(row, total, NULL, right, 13, size)
|
2018-08-01 00:49:49 +08:00
|
|
|
|
|
|
|
/* Label this section. */
|
|
|
|
header_size.width -= 8;
|
|
|
|
emitter_table_printf(emitter, "extents:");
|
|
|
|
emitter_table_row(emitter, &header_row);
|
|
|
|
emitter_json_array_kv_begin(emitter, "extents");
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_arenas_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 0, "stats.arenas");
|
|
|
|
stats_arenas_mib[2] = i;
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 3, "extents");
|
|
|
|
|
2018-08-01 00:49:49 +08:00
|
|
|
in_gap = false;
|
|
|
|
for (j = 0; j < SC_NPSIZES; j++) {
|
|
|
|
size_t ndirty, nmuzzy, nretained, total, dirty_bytes,
|
|
|
|
muzzy_bytes, retained_bytes, total_bytes;
|
2020-12-18 06:01:56 +08:00
|
|
|
stats_arenas_mib[4] = j;
|
|
|
|
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "ndirty", &ndirty, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nmuzzy", &nmuzzy, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "nretained", &nretained, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "dirty_bytes", &dirty_bytes,
|
|
|
|
size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "muzzy_bytes", &muzzy_bytes,
|
|
|
|
size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 5, "retained_bytes",
|
2018-08-01 00:49:49 +08:00
|
|
|
&retained_bytes, size_t);
|
2020-12-18 06:01:56 +08:00
|
|
|
|
2018-08-01 00:49:49 +08:00
|
|
|
total = ndirty + nmuzzy + nretained;
|
|
|
|
total_bytes = dirty_bytes + muzzy_bytes + retained_bytes;
|
|
|
|
|
|
|
|
in_gap_prev = in_gap;
|
|
|
|
in_gap = (total == 0);
|
|
|
|
|
|
|
|
if (in_gap_prev && !in_gap) {
|
|
|
|
emitter_table_printf(emitter,
|
|
|
|
" ---\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter_json_object_begin(emitter);
|
|
|
|
emitter_json_kv(emitter, "ndirty", emitter_type_size, &ndirty);
|
|
|
|
emitter_json_kv(emitter, "nmuzzy", emitter_type_size, &nmuzzy);
|
|
|
|
emitter_json_kv(emitter, "nretained", emitter_type_size,
|
|
|
|
&nretained);
|
|
|
|
|
|
|
|
emitter_json_kv(emitter, "dirty_bytes", emitter_type_size,
|
|
|
|
&dirty_bytes);
|
|
|
|
emitter_json_kv(emitter, "muzzy_bytes", emitter_type_size,
|
|
|
|
&muzzy_bytes);
|
|
|
|
emitter_json_kv(emitter, "retained_bytes", emitter_type_size,
|
|
|
|
&retained_bytes);
|
|
|
|
emitter_json_object_end(emitter);
|
|
|
|
|
|
|
|
col_size.size_val = sz_pind2sz(j);
|
|
|
|
col_ind.size_val = j;
|
|
|
|
col_ndirty.size_val = ndirty;
|
|
|
|
col_dirty.size_val = dirty_bytes;
|
|
|
|
col_nmuzzy.size_val = nmuzzy;
|
|
|
|
col_muzzy.size_val = muzzy_bytes;
|
|
|
|
col_nretained.size_val = nretained;
|
|
|
|
col_retained.size_val = retained_bytes;
|
|
|
|
col_ntotal.size_val = total;
|
|
|
|
col_total.size_val = total_bytes;
|
|
|
|
|
|
|
|
if (!in_gap) {
|
|
|
|
emitter_table_row(emitter, &row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
emitter_json_array_end(emitter); /* Close "extents". */
|
|
|
|
if (in_gap) {
|
|
|
|
emitter_table_printf(emitter, " ---\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-05 03:01:52 +08:00
|
|
|
static void
|
2020-12-01 11:06:50 +08:00
|
|
|
stats_arena_hpa_shard_print(emitter_t *emitter, unsigned i, uint64_t uptime) {
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_row_t header_row;
|
|
|
|
emitter_row_init(&header_row);
|
|
|
|
emitter_row_t row;
|
|
|
|
emitter_row_init(&row);
|
|
|
|
|
2020-12-01 11:06:50 +08:00
|
|
|
uint64_t nevictions;
|
|
|
|
|
2020-11-10 05:49:30 +08:00
|
|
|
size_t npageslabs_huge;
|
|
|
|
size_t nactive_huge;
|
|
|
|
size_t ninactive_huge;
|
|
|
|
|
|
|
|
size_t npageslabs_nonhuge;
|
|
|
|
size_t nactive_nonhuge;
|
|
|
|
size_t ninactive_nonhuge;
|
|
|
|
|
2020-12-01 11:06:50 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.nevictions",
|
|
|
|
i, &nevictions, uint64_t);
|
|
|
|
|
2020-11-10 05:49:30 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.npageslabs_huge",
|
|
|
|
i, &npageslabs_huge, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.nactive_huge",
|
|
|
|
i, &nactive_huge, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.ninactive_huge",
|
|
|
|
i, &ninactive_huge, size_t);
|
|
|
|
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.npageslabs_nonhuge",
|
|
|
|
i, &npageslabs_nonhuge, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.nactive_nonhuge",
|
|
|
|
i, &nactive_nonhuge, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_shard.full_slabs.ninactive_nonhuge",
|
|
|
|
i, &ninactive_nonhuge, size_t);
|
2020-09-05 03:01:52 +08:00
|
|
|
|
2020-10-17 04:14:59 +08:00
|
|
|
size_t sec_bytes;
|
|
|
|
CTL_M2_GET("stats.arenas.0.hpa_sec_bytes", i, &sec_bytes, size_t);
|
|
|
|
emitter_kv(emitter, "sec_bytes", "Bytes in small extent cache",
|
|
|
|
emitter_type_size, &sec_bytes);
|
|
|
|
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_table_printf(emitter,
|
|
|
|
"HPA shard stats:\n"
|
2020-12-01 11:06:50 +08:00
|
|
|
" Evictions: %" FMTu64 " (%" FMTu64 " / sec)\n"
|
2020-09-05 03:01:52 +08:00
|
|
|
" In full slabs:\n"
|
2020-11-10 05:49:30 +08:00
|
|
|
" npageslabs: %zu huge, %zu nonhuge\n"
|
|
|
|
" nactive: %zu huge, %zu nonhuge \n"
|
|
|
|
" ninactive: %zu huge, %zu nonhuge \n",
|
2020-12-01 11:06:50 +08:00
|
|
|
nevictions, rate_per_second(nevictions, uptime),
|
|
|
|
npageslabs_huge, npageslabs_nonhuge,
|
|
|
|
nactive_huge, nactive_nonhuge,
|
2020-11-10 05:49:30 +08:00
|
|
|
ninactive_huge, ninactive_nonhuge);
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "hpa_shard");
|
2020-12-01 11:06:50 +08:00
|
|
|
emitter_json_kv(emitter, "nevictions", emitter_type_uint64,
|
|
|
|
&nevictions);
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "full_slabs");
|
2020-11-10 05:49:30 +08:00
|
|
|
emitter_json_kv(emitter, "npageslabs_huge", emitter_type_size,
|
|
|
|
&npageslabs_huge);
|
|
|
|
emitter_json_kv(emitter, "npageslabs_nonhuge", emitter_type_size,
|
|
|
|
&npageslabs_nonhuge);
|
|
|
|
emitter_json_kv(emitter, "nactive_huge", emitter_type_size,
|
|
|
|
&nactive_huge);
|
|
|
|
emitter_json_kv(emitter, "nactive_nonhuge", emitter_type_size,
|
|
|
|
&nactive_nonhuge);
|
|
|
|
emitter_json_kv(emitter, "ninactive_huge", emitter_type_size,
|
|
|
|
&ninactive_huge);
|
|
|
|
emitter_json_kv(emitter, "ninactive_nonhuge", emitter_type_size,
|
|
|
|
&ninactive_nonhuge);
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_json_object_end(emitter); /* End "full_slabs" */
|
|
|
|
|
|
|
|
COL_HDR(row, size, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, ind, NULL, right, 4, unsigned)
|
2020-11-10 05:49:30 +08:00
|
|
|
COL_HDR(row, npageslabs_huge, NULL, right, 16, size)
|
|
|
|
COL_HDR(row, nactive_huge, NULL, right, 16, size)
|
|
|
|
COL_HDR(row, ninactive_huge, NULL, right, 16, size)
|
|
|
|
COL_HDR(row, npageslabs_nonhuge, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, nactive_nonhuge, NULL, right, 20, size)
|
|
|
|
COL_HDR(row, ninactive_nonhuge, NULL, right, 20, size)
|
2020-09-05 03:01:52 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_arenas_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 0, "stats.arenas");
|
|
|
|
stats_arenas_mib[2] = i;
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 3, "hpa_shard.nonfull_slabs");
|
|
|
|
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_table_row(emitter, &header_row);
|
|
|
|
emitter_json_array_kv_begin(emitter, "nonfull_slabs");
|
|
|
|
bool in_gap = false;
|
|
|
|
for (pszind_t j = 0; j < PSSET_NPSIZES; j++) {
|
2020-12-18 06:01:56 +08:00
|
|
|
stats_arenas_mib[5] = j;
|
|
|
|
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "npageslabs_huge",
|
|
|
|
&npageslabs_huge, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "nactive_huge",
|
|
|
|
&nactive_huge, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "ninactive_huge",
|
|
|
|
&ninactive_huge, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "npageslabs_nonhuge",
|
|
|
|
&npageslabs_nonhuge, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "nactive_nonhuge",
|
|
|
|
&nactive_nonhuge, size_t);
|
|
|
|
CTL_LEAF(stats_arenas_mib, 6, "ninactive_nonhuge",
|
|
|
|
&ninactive_nonhuge, size_t);
|
2020-09-05 03:01:52 +08:00
|
|
|
|
|
|
|
bool in_gap_prev = in_gap;
|
2020-11-10 05:49:30 +08:00
|
|
|
in_gap = (npageslabs_huge == 0 && npageslabs_nonhuge == 0);
|
2020-09-05 03:01:52 +08:00
|
|
|
if (in_gap_prev && !in_gap) {
|
|
|
|
emitter_table_printf(emitter,
|
|
|
|
" ---\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
col_size.size_val = sz_pind2sz(j);
|
|
|
|
col_ind.size_val = j;
|
2020-11-10 05:49:30 +08:00
|
|
|
col_npageslabs_huge.size_val = npageslabs_huge;
|
|
|
|
col_nactive_huge.size_val = nactive_huge;
|
|
|
|
col_ninactive_huge.size_val = ninactive_huge;
|
|
|
|
col_npageslabs_nonhuge.size_val = npageslabs_nonhuge;
|
|
|
|
col_nactive_nonhuge.size_val = nactive_nonhuge;
|
|
|
|
col_ninactive_nonhuge.size_val = ninactive_nonhuge;
|
2020-09-05 03:01:52 +08:00
|
|
|
if (!in_gap) {
|
|
|
|
emitter_table_row(emitter, &row);
|
|
|
|
}
|
|
|
|
|
|
|
|
emitter_json_object_begin(emitter);
|
2020-11-10 05:49:30 +08:00
|
|
|
emitter_json_kv(emitter, "npageslabs_huge", emitter_type_size,
|
|
|
|
&npageslabs_huge);
|
|
|
|
emitter_json_kv(emitter, "nactive_huge", emitter_type_size,
|
|
|
|
&nactive_huge);
|
|
|
|
emitter_json_kv(emitter, "ninactive_huge", emitter_type_size,
|
|
|
|
&ninactive_huge);
|
|
|
|
emitter_json_kv(emitter, "npageslabs_nonhuge", emitter_type_size,
|
|
|
|
&npageslabs_nonhuge);
|
|
|
|
emitter_json_kv(emitter, "nactive_nonhuge", emitter_type_size,
|
|
|
|
&nactive_nonhuge);
|
|
|
|
emitter_json_kv(emitter, "ninactive_nonhuge", emitter_type_size,
|
|
|
|
&ninactive_huge);
|
2020-09-05 03:01:52 +08:00
|
|
|
emitter_json_object_end(emitter);
|
|
|
|
}
|
|
|
|
emitter_json_array_end(emitter); /* End "nonfull_slabs" */
|
|
|
|
emitter_json_object_end(emitter); /* End "hpa_shard" */
|
2020-12-19 03:06:22 +08:00
|
|
|
if (in_gap) {
|
|
|
|
emitter_table_printf(emitter, " ---\n");
|
|
|
|
}
|
2020-09-05 03:01:52 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 04:14:05 +08:00
|
|
|
static void
|
2018-12-11 03:29:44 +08:00
|
|
|
stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind, uint64_t uptime) {
|
2018-03-06 10:46:44 +08:00
|
|
|
emitter_row_t row;
|
|
|
|
emitter_col_t col_name;
|
|
|
|
emitter_col_t col64[mutex_prof_num_uint64_t_counters];
|
|
|
|
emitter_col_t col32[mutex_prof_num_uint32_t_counters];
|
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_row_init(&row);
|
|
|
|
mutex_stats_init_cols(&row, "", &col_name, col64, col32);
|
2018-03-06 10:46:44 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "mutexes");
|
2018-03-06 10:46:44 +08:00
|
|
|
emitter_table_row(emitter, &row);
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_arenas_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 0, "stats.arenas");
|
|
|
|
stats_arenas_mib[2] = arena_ind;
|
|
|
|
CTL_LEAF_PREPARE(stats_arenas_mib, 3, "mutexes");
|
|
|
|
|
2018-03-06 10:46:44 +08:00
|
|
|
for (mutex_prof_arena_ind_t i = 0; i < mutex_prof_num_arena_mutexes;
|
|
|
|
i++) {
|
|
|
|
const char *name = arena_mutex_names[i];
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, name);
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_arena(stats_arenas_mib, 4, name, &col_name,
|
|
|
|
col64, col32, uptime);
|
2018-03-06 10:46:44 +08:00
|
|
|
mutex_stats_emit(emitter, &row, col64, col32);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close the mutex dict. */
|
2017-03-11 04:14:05 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* End "mutexes". */
|
2017-03-11 04:14:05 +08:00
|
|
|
}
|
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2010-01-28 05:10:55 +08:00
|
|
|
static void
|
2018-03-06 05:03:22 +08:00
|
|
|
stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
2020-09-05 03:01:52 +08:00
|
|
|
bool mutex, bool extents, bool hpa) {
|
2011-03-19 04:41:33 +08:00
|
|
|
unsigned nthreads;
|
2012-10-12 04:53:15 +08:00
|
|
|
const char *dss;
|
2017-05-18 01:47:00 +08:00
|
|
|
ssize_t dirty_decay_ms, muzzy_decay_ms;
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
size_t page, pactive, pdirty, pmuzzy, mapped, retained;
|
2018-08-02 05:14:33 +08:00
|
|
|
size_t base, internal, resident, metadata_thp, extent_avail;
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
uint64_t dirty_npurge, dirty_nmadvise, dirty_purged;
|
|
|
|
uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged;
|
2010-01-28 05:10:55 +08:00
|
|
|
size_t small_allocated;
|
2019-05-07 07:36:55 +08:00
|
|
|
uint64_t small_nmalloc, small_ndalloc, small_nrequests, small_nfills,
|
|
|
|
small_nflushes;
|
2016-06-01 05:50:21 +08:00
|
|
|
size_t large_allocated;
|
2019-05-07 07:36:55 +08:00
|
|
|
uint64_t large_nmalloc, large_ndalloc, large_nrequests, large_nfills,
|
|
|
|
large_nflushes;
|
2019-07-16 06:56:05 +08:00
|
|
|
size_t tcache_bytes, abandoned_vm;
|
2017-05-17 04:56:00 +08:00
|
|
|
uint64_t uptime;
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2012-04-02 22:15:42 +08:00
|
|
|
CTL_GET("arenas.page", &page, size_t);
|
2010-01-30 03:24:19 +08:00
|
|
|
|
2015-03-21 09:08:10 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned);
|
2018-03-06 08:26:32 +08:00
|
|
|
emitter_kv(emitter, "nthreads", "assigned threads",
|
|
|
|
emitter_type_unsigned, &nthreads);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2017-05-17 04:56:00 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.uptime", i, &uptime, uint64_t);
|
2018-03-06 08:26:32 +08:00
|
|
|
emitter_kv(emitter, "uptime_ns", "uptime", emitter_type_uint64,
|
|
|
|
&uptime);
|
2017-05-17 04:56:00 +08:00
|
|
|
|
2015-03-21 09:08:10 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *);
|
2018-03-06 08:26:32 +08:00
|
|
|
emitter_kv(emitter, "dss", "dss allocation precedence",
|
|
|
|
emitter_type_string, &dss);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2017-05-18 01:47:00 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.dirty_decay_ms", i, &dirty_decay_ms,
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
ssize_t);
|
2017-05-18 01:47:00 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.muzzy_decay_ms", i, &muzzy_decay_ms,
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
ssize_t);
|
2015-03-21 09:08:10 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t);
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.pmuzzy", i, &pmuzzy, size_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.dirty_npurge", i, &dirty_npurge, uint64_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.dirty_nmadvise", i, &dirty_nmadvise,
|
|
|
|
uint64_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.dirty_purged", i, &dirty_purged, uint64_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.muzzy_npurge", i, &muzzy_npurge, uint64_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.muzzy_nmadvise", i, &muzzy_nmadvise,
|
|
|
|
uint64_t);
|
|
|
|
CTL_M2_GET("stats.arenas.0.muzzy_purged", i, &muzzy_purged, uint64_t);
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
emitter_row_t decay_row;
|
|
|
|
emitter_row_init(&decay_row);
|
|
|
|
|
|
|
|
/* JSON-style emission. */
|
|
|
|
emitter_json_kv(emitter, "dirty_decay_ms", emitter_type_ssize,
|
|
|
|
&dirty_decay_ms);
|
|
|
|
emitter_json_kv(emitter, "muzzy_decay_ms", emitter_type_ssize,
|
|
|
|
&muzzy_decay_ms);
|
|
|
|
|
|
|
|
emitter_json_kv(emitter, "pactive", emitter_type_size, &pactive);
|
|
|
|
emitter_json_kv(emitter, "pdirty", emitter_type_size, &pdirty);
|
|
|
|
emitter_json_kv(emitter, "pmuzzy", emitter_type_size, &pmuzzy);
|
|
|
|
|
|
|
|
emitter_json_kv(emitter, "dirty_npurge", emitter_type_uint64,
|
|
|
|
&dirty_npurge);
|
|
|
|
emitter_json_kv(emitter, "dirty_nmadvise", emitter_type_uint64,
|
|
|
|
&dirty_nmadvise);
|
|
|
|
emitter_json_kv(emitter, "dirty_purged", emitter_type_uint64,
|
|
|
|
&dirty_purged);
|
|
|
|
|
|
|
|
emitter_json_kv(emitter, "muzzy_npurge", emitter_type_uint64,
|
|
|
|
&muzzy_npurge);
|
|
|
|
emitter_json_kv(emitter, "muzzy_nmadvise", emitter_type_uint64,
|
|
|
|
&muzzy_nmadvise);
|
|
|
|
emitter_json_kv(emitter, "muzzy_purged", emitter_type_uint64,
|
|
|
|
&muzzy_purged);
|
|
|
|
|
|
|
|
/* Table-style emission. */
|
2018-12-11 03:29:44 +08:00
|
|
|
COL(decay_row, decay_type, right, 9, title);
|
|
|
|
col_decay_type.str_val = "decaying:";
|
|
|
|
|
|
|
|
COL(decay_row, decay_time, right, 6, title);
|
|
|
|
col_decay_time.str_val = "time";
|
|
|
|
|
|
|
|
COL(decay_row, decay_npages, right, 13, title);
|
|
|
|
col_decay_npages.str_val = "npages";
|
|
|
|
|
|
|
|
COL(decay_row, decay_sweeps, right, 13, title);
|
|
|
|
col_decay_sweeps.str_val = "sweeps";
|
|
|
|
|
|
|
|
COL(decay_row, decay_madvises, right, 13, title);
|
|
|
|
col_decay_madvises.str_val = "madvises";
|
|
|
|
|
|
|
|
COL(decay_row, decay_purged, right, 13, title);
|
|
|
|
col_decay_purged.str_val = "purged";
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
/* Title row. */
|
|
|
|
emitter_table_row(emitter, &decay_row);
|
|
|
|
|
|
|
|
/* Dirty row. */
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_type.str_val = "dirty:";
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
if (dirty_decay_ms >= 0) {
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_time.type = emitter_type_ssize;
|
|
|
|
col_decay_time.ssize_val = dirty_decay_ms;
|
2016-11-01 13:30:49 +08:00
|
|
|
} else {
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_time.type = emitter_type_title;
|
|
|
|
col_decay_time.str_val = "N/A";
|
2018-03-06 08:26:32 +08:00
|
|
|
}
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_npages.type = emitter_type_size;
|
|
|
|
col_decay_npages.size_val = pdirty;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_sweeps.type = emitter_type_uint64;
|
|
|
|
col_decay_sweeps.uint64_val = dirty_npurge;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_madvises.type = emitter_type_uint64;
|
|
|
|
col_decay_madvises.uint64_val = dirty_nmadvise;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_purged.type = emitter_type_uint64;
|
|
|
|
col_decay_purged.uint64_val = dirty_purged;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
emitter_table_row(emitter, &decay_row);
|
|
|
|
|
|
|
|
/* Muzzy row. */
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_type.str_val = "muzzy:";
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
if (muzzy_decay_ms >= 0) {
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_time.type = emitter_type_ssize;
|
|
|
|
col_decay_time.ssize_val = muzzy_decay_ms;
|
2018-03-06 08:26:32 +08:00
|
|
|
} else {
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_time.type = emitter_type_title;
|
|
|
|
col_decay_time.str_val = "N/A";
|
2018-03-06 08:26:32 +08:00
|
|
|
}
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_npages.type = emitter_type_size;
|
|
|
|
col_decay_npages.size_val = pmuzzy;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_sweeps.type = emitter_type_uint64;
|
|
|
|
col_decay_sweeps.uint64_val = muzzy_npurge;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_madvises.type = emitter_type_uint64;
|
|
|
|
col_decay_madvises.uint64_val = muzzy_nmadvise;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_decay_purged.type = emitter_type_uint64;
|
|
|
|
col_decay_purged.uint64_val = muzzy_purged;
|
2018-03-06 08:26:32 +08:00
|
|
|
|
|
|
|
emitter_table_row(emitter, &decay_row);
|
|
|
|
|
2018-03-06 08:52:34 +08:00
|
|
|
/* Small / large / total allocation counts. */
|
|
|
|
emitter_row_t alloc_count_row;
|
|
|
|
emitter_row_init(&alloc_count_row);
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
COL(alloc_count_row, count_title, left, 21, title);
|
|
|
|
col_count_title.str_val = "";
|
|
|
|
|
|
|
|
COL(alloc_count_row, count_allocated, right, 16, title);
|
|
|
|
col_count_allocated.str_val = "allocated";
|
|
|
|
|
|
|
|
COL(alloc_count_row, count_nmalloc, right, 16, title);
|
|
|
|
col_count_nmalloc.str_val = "nmalloc";
|
2019-10-25 04:16:09 +08:00
|
|
|
COL(alloc_count_row, count_nmalloc_ps, right, 10, title);
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nmalloc_ps.str_val = "(#/sec)";
|
|
|
|
|
|
|
|
COL(alloc_count_row, count_ndalloc, right, 16, title);
|
|
|
|
col_count_ndalloc.str_val = "ndalloc";
|
2019-10-25 04:16:09 +08:00
|
|
|
COL(alloc_count_row, count_ndalloc_ps, right, 10, title);
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_ndalloc_ps.str_val = "(#/sec)";
|
|
|
|
|
|
|
|
COL(alloc_count_row, count_nrequests, right, 16, title);
|
|
|
|
col_count_nrequests.str_val = "nrequests";
|
2019-01-19 07:51:01 +08:00
|
|
|
COL(alloc_count_row, count_nrequests_ps, right, 10, title);
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nrequests_ps.str_val = "(#/sec)";
|
2018-03-06 08:52:34 +08:00
|
|
|
|
2019-05-07 07:36:55 +08:00
|
|
|
COL(alloc_count_row, count_nfills, right, 16, title);
|
|
|
|
col_count_nfills.str_val = "nfill";
|
|
|
|
COL(alloc_count_row, count_nfills_ps, right, 10, title);
|
|
|
|
col_count_nfills_ps.str_val = "(#/sec)";
|
|
|
|
|
|
|
|
COL(alloc_count_row, count_nflushes, right, 16, title);
|
|
|
|
col_count_nflushes.str_val = "nflush";
|
|
|
|
COL(alloc_count_row, count_nflushes_ps, right, 10, title);
|
|
|
|
col_count_nflushes_ps.str_val = "(#/sec)";
|
|
|
|
|
2018-03-06 08:52:34 +08:00
|
|
|
emitter_table_row(emitter, &alloc_count_row);
|
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nmalloc_ps.type = emitter_type_uint64;
|
|
|
|
col_count_ndalloc_ps.type = emitter_type_uint64;
|
|
|
|
col_count_nrequests_ps.type = emitter_type_uint64;
|
2019-05-07 07:36:55 +08:00
|
|
|
col_count_nfills_ps.type = emitter_type_uint64;
|
|
|
|
col_count_nflushes_ps.type = emitter_type_uint64;
|
2018-12-11 03:29:44 +08:00
|
|
|
|
2018-03-06 08:52:34 +08:00
|
|
|
#define GET_AND_EMIT_ALLOC_STAT(small_or_large, name, valtype) \
|
|
|
|
CTL_M2_GET("stats.arenas.0." #small_or_large "." #name, i, \
|
|
|
|
&small_or_large##_##name, valtype##_t); \
|
|
|
|
emitter_json_kv(emitter, #name, emitter_type_##valtype, \
|
|
|
|
&small_or_large##_##name); \
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_##name.type = emitter_type_##valtype; \
|
|
|
|
col_count_##name.valtype##_val = small_or_large##_##name;
|
2018-03-06 08:52:34 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "small");
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_title.str_val = "small:";
|
2018-03-06 08:52:34 +08:00
|
|
|
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, allocated, size)
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, nmalloc, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nmalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nmalloc.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, ndalloc, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_ndalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_ndalloc.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, nrequests, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nrequests_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nrequests.uint64_val, uptime);
|
2019-05-07 07:36:55 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, nfills, uint64)
|
|
|
|
col_count_nfills_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nfills.uint64_val, uptime);
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(small, nflushes, uint64)
|
|
|
|
col_count_nflushes_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nflushes.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
|
|
|
|
emitter_table_row(emitter, &alloc_count_row);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "small". */
|
2018-03-06 08:52:34 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "large");
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_title.str_val = "large:";
|
2018-03-06 08:52:34 +08:00
|
|
|
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, allocated, size)
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, nmalloc, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nmalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nmalloc.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, ndalloc, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_ndalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_ndalloc.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, nrequests, uint64)
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_nrequests_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nrequests.uint64_val, uptime);
|
2019-05-07 07:36:55 +08:00
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, nfills, uint64)
|
|
|
|
col_count_nfills_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nfills.uint64_val, uptime);
|
|
|
|
GET_AND_EMIT_ALLOC_STAT(large, nflushes, uint64)
|
|
|
|
col_count_nflushes_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nflushes.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
|
|
|
|
emitter_table_row(emitter, &alloc_count_row);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "large". */
|
2018-03-06 08:52:34 +08:00
|
|
|
|
|
|
|
#undef GET_AND_EMIT_ALLOC_STAT
|
|
|
|
|
|
|
|
/* Aggregated small + large stats are emitter only in table mode. */
|
2018-12-11 03:29:44 +08:00
|
|
|
col_count_title.str_val = "total:";
|
|
|
|
col_count_allocated.size_val = small_allocated + large_allocated;
|
|
|
|
col_count_nmalloc.uint64_val = small_nmalloc + large_nmalloc;
|
|
|
|
col_count_ndalloc.uint64_val = small_ndalloc + large_ndalloc;
|
|
|
|
col_count_nrequests.uint64_val = small_nrequests + large_nrequests;
|
2019-05-07 07:36:55 +08:00
|
|
|
col_count_nfills.uint64_val = small_nfills + large_nfills;
|
|
|
|
col_count_nflushes.uint64_val = small_nflushes + large_nflushes;
|
2019-01-19 07:22:44 +08:00
|
|
|
col_count_nmalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nmalloc.uint64_val, uptime);
|
|
|
|
col_count_ndalloc_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_ndalloc.uint64_val, uptime);
|
|
|
|
col_count_nrequests_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nrequests.uint64_val, uptime);
|
2019-05-07 07:36:55 +08:00
|
|
|
col_count_nfills_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nfills.uint64_val, uptime);
|
|
|
|
col_count_nflushes_ps.uint64_val =
|
|
|
|
rate_per_second(col_count_nflushes.uint64_val, uptime);
|
2018-03-06 08:52:34 +08:00
|
|
|
emitter_table_row(emitter, &alloc_count_row);
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2018-03-06 09:58:02 +08:00
|
|
|
emitter_row_t mem_count_row;
|
|
|
|
emitter_row_init(&mem_count_row);
|
|
|
|
|
|
|
|
emitter_col_t mem_count_title;
|
|
|
|
emitter_col_init(&mem_count_title, &mem_count_row);
|
|
|
|
mem_count_title.justify = emitter_justify_left;
|
2018-05-18 01:53:54 +08:00
|
|
|
mem_count_title.width = 21;
|
2018-03-06 09:58:02 +08:00
|
|
|
mem_count_title.type = emitter_type_title;
|
|
|
|
mem_count_title.str_val = "";
|
|
|
|
|
|
|
|
emitter_col_t mem_count_val;
|
|
|
|
emitter_col_init(&mem_count_val, &mem_count_row);
|
|
|
|
mem_count_val.justify = emitter_justify_right;
|
2018-05-18 01:53:54 +08:00
|
|
|
mem_count_val.width = 16;
|
2018-03-06 09:58:02 +08:00
|
|
|
mem_count_val.type = emitter_type_title;
|
|
|
|
mem_count_val.str_val = "";
|
|
|
|
|
|
|
|
emitter_table_row(emitter, &mem_count_row);
|
|
|
|
mem_count_val.type = emitter_type_size;
|
|
|
|
|
|
|
|
/* Active count in bytes is emitted only in table mode. */
|
|
|
|
mem_count_title.str_val = "active:";
|
|
|
|
mem_count_val.size_val = pactive * page;
|
|
|
|
emitter_table_row(emitter, &mem_count_row);
|
|
|
|
|
|
|
|
#define GET_AND_EMIT_MEM_STAT(stat) \
|
|
|
|
CTL_M2_GET("stats.arenas.0."#stat, i, &stat, size_t); \
|
|
|
|
emitter_json_kv(emitter, #stat, emitter_type_size, &stat); \
|
|
|
|
mem_count_title.str_val = #stat":"; \
|
|
|
|
mem_count_val.size_val = stat; \
|
|
|
|
emitter_table_row(emitter, &mem_count_row);
|
|
|
|
|
|
|
|
GET_AND_EMIT_MEM_STAT(mapped)
|
|
|
|
GET_AND_EMIT_MEM_STAT(retained)
|
|
|
|
GET_AND_EMIT_MEM_STAT(base)
|
|
|
|
GET_AND_EMIT_MEM_STAT(internal)
|
|
|
|
GET_AND_EMIT_MEM_STAT(metadata_thp)
|
|
|
|
GET_AND_EMIT_MEM_STAT(tcache_bytes)
|
|
|
|
GET_AND_EMIT_MEM_STAT(resident)
|
2019-07-16 06:56:05 +08:00
|
|
|
GET_AND_EMIT_MEM_STAT(abandoned_vm)
|
2018-08-02 05:14:33 +08:00
|
|
|
GET_AND_EMIT_MEM_STAT(extent_avail)
|
2018-03-06 09:58:02 +08:00
|
|
|
#undef GET_AND_EMIT_MEM_STAT
|
2016-12-23 06:39:10 +08:00
|
|
|
|
2018-03-06 10:46:44 +08:00
|
|
|
if (mutex) {
|
2018-12-11 03:29:44 +08:00
|
|
|
stats_arena_mutexes_print(emitter, i, uptime);
|
2018-03-06 10:46:44 +08:00
|
|
|
}
|
2018-03-07 10:50:53 +08:00
|
|
|
if (bins) {
|
2018-12-11 03:29:44 +08:00
|
|
|
stats_arena_bins_print(emitter, mutex, i, uptime);
|
2018-03-07 10:50:53 +08:00
|
|
|
}
|
2017-01-16 08:56:30 +08:00
|
|
|
if (large) {
|
2018-12-11 03:29:44 +08:00
|
|
|
stats_arena_lextents_print(emitter, i, uptime);
|
2017-01-16 08:56:30 +08:00
|
|
|
}
|
2018-08-01 00:49:49 +08:00
|
|
|
if (extents) {
|
|
|
|
stats_arena_extents_print(emitter, i);
|
|
|
|
}
|
2020-09-05 03:01:52 +08:00
|
|
|
if (hpa) {
|
2020-12-01 11:06:50 +08:00
|
|
|
stats_arena_hpa_shard_print(emitter, i, uptime);
|
2020-09-05 03:01:52 +08:00
|
|
|
}
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2016-11-01 13:30:49 +08:00
|
|
|
static void
|
2018-03-02 11:01:05 +08:00
|
|
|
stats_general_print(emitter_t *emitter) {
|
2016-11-01 13:30:49 +08:00
|
|
|
const char *cpv;
|
2018-03-02 09:38:15 +08:00
|
|
|
bool bv, bv2;
|
2016-11-01 13:30:49 +08:00
|
|
|
unsigned uv;
|
|
|
|
uint32_t u32v;
|
|
|
|
uint64_t u64v;
|
2020-01-14 14:29:17 +08:00
|
|
|
int64_t i64v;
|
2018-03-02 09:38:15 +08:00
|
|
|
ssize_t ssv, ssv2;
|
2020-01-14 14:29:17 +08:00
|
|
|
size_t sv, bsz, usz, i64sz, ssz, sssz, cpsz;
|
2016-11-01 13:30:49 +08:00
|
|
|
|
|
|
|
bsz = sizeof(bool);
|
|
|
|
usz = sizeof(unsigned);
|
|
|
|
ssz = sizeof(size_t);
|
|
|
|
sssz = sizeof(ssize_t);
|
|
|
|
cpsz = sizeof(const char *);
|
2020-01-14 14:29:17 +08:00
|
|
|
i64sz = sizeof(int64_t);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
|
|
|
CTL_GET("version", &cpv, const char *);
|
2018-03-02 09:38:15 +08:00
|
|
|
emitter_kv(emitter, "version", "Version", emitter_type_string, &cpv);
|
2010-01-17 01:53:50 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
/* config. */
|
2018-03-02 09:38:15 +08:00
|
|
|
emitter_dict_begin(emitter, "config", "Build-time option settings");
|
|
|
|
#define CONFIG_WRITE_BOOL(name) \
|
|
|
|
do { \
|
|
|
|
CTL_GET("config."#name, &bv, bool); \
|
|
|
|
emitter_kv(emitter, #name, "config."#name, \
|
|
|
|
emitter_type_bool, &bv); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
CONFIG_WRITE_BOOL(cache_oblivious);
|
|
|
|
CONFIG_WRITE_BOOL(debug);
|
|
|
|
CONFIG_WRITE_BOOL(fill);
|
|
|
|
CONFIG_WRITE_BOOL(lazy_lock);
|
|
|
|
emitter_kv(emitter, "malloc_conf", "config.malloc_conf",
|
|
|
|
emitter_type_string, &config_malloc_conf);
|
|
|
|
|
2019-03-23 08:13:45 +08:00
|
|
|
CONFIG_WRITE_BOOL(opt_safety_checks);
|
2018-03-02 09:38:15 +08:00
|
|
|
CONFIG_WRITE_BOOL(prof);
|
|
|
|
CONFIG_WRITE_BOOL(prof_libgcc);
|
|
|
|
CONFIG_WRITE_BOOL(prof_libunwind);
|
|
|
|
CONFIG_WRITE_BOOL(stats);
|
|
|
|
CONFIG_WRITE_BOOL(utrace);
|
|
|
|
CONFIG_WRITE_BOOL(xmalloc);
|
|
|
|
#undef CONFIG_WRITE_BOOL
|
|
|
|
emitter_dict_end(emitter); /* Close "config" dict. */
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
/* opt. */
|
2018-03-02 09:38:15 +08:00
|
|
|
#define OPT_WRITE(name, var, size, emitter_type) \
|
2018-03-15 11:06:04 +08:00
|
|
|
if (je_mallctl("opt."name, (void *)&var, &size, NULL, 0) == \
|
2018-03-02 09:38:15 +08:00
|
|
|
0) { \
|
2018-03-15 11:06:04 +08:00
|
|
|
emitter_kv(emitter, name, "opt."name, emitter_type, \
|
2018-03-02 09:38:15 +08:00
|
|
|
&var); \
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
2010-10-24 09:37:06 +08:00
|
|
|
|
2018-03-02 09:38:15 +08:00
|
|
|
#define OPT_WRITE_MUTABLE(name, var1, var2, size, emitter_type, \
|
|
|
|
altname) \
|
2018-03-15 11:06:04 +08:00
|
|
|
if (je_mallctl("opt."name, (void *)&var1, &size, NULL, 0) == \
|
|
|
|
0 && je_mallctl(altname, (void *)&var2, &size, NULL, 0) \
|
2018-03-02 09:38:15 +08:00
|
|
|
== 0) { \
|
2018-03-15 11:06:04 +08:00
|
|
|
emitter_kv_note(emitter, name, "opt."name, \
|
|
|
|
emitter_type, &var1, altname, emitter_type, \
|
2018-03-02 09:38:15 +08:00
|
|
|
&var2); \
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
2010-10-24 09:37:06 +08:00
|
|
|
|
2018-03-02 09:38:15 +08:00
|
|
|
#define OPT_WRITE_BOOL(name) OPT_WRITE(name, bv, bsz, emitter_type_bool)
|
|
|
|
#define OPT_WRITE_BOOL_MUTABLE(name, altname) \
|
|
|
|
OPT_WRITE_MUTABLE(name, bv, bv2, bsz, emitter_type_bool, altname)
|
|
|
|
|
|
|
|
#define OPT_WRITE_UNSIGNED(name) \
|
|
|
|
OPT_WRITE(name, uv, usz, emitter_type_unsigned)
|
|
|
|
|
2020-01-14 14:29:17 +08:00
|
|
|
#define OPT_WRITE_INT64(name) \
|
|
|
|
OPT_WRITE(name, i64v, i64sz, emitter_type_int64)
|
|
|
|
|
2018-06-05 02:06:23 +08:00
|
|
|
#define OPT_WRITE_SIZE_T(name) \
|
|
|
|
OPT_WRITE(name, sv, ssz, emitter_type_size)
|
2018-03-02 09:38:15 +08:00
|
|
|
#define OPT_WRITE_SSIZE_T(name) \
|
|
|
|
OPT_WRITE(name, ssv, sssz, emitter_type_ssize)
|
|
|
|
#define OPT_WRITE_SSIZE_T_MUTABLE(name, altname) \
|
|
|
|
OPT_WRITE_MUTABLE(name, ssv, ssv2, sssz, emitter_type_ssize, \
|
|
|
|
altname)
|
|
|
|
|
|
|
|
#define OPT_WRITE_CHAR_P(name) \
|
|
|
|
OPT_WRITE(name, cpv, cpsz, emitter_type_string)
|
|
|
|
|
|
|
|
emitter_dict_begin(emitter, "opt", "Run-time option settings");
|
|
|
|
|
2018-03-15 11:06:04 +08:00
|
|
|
OPT_WRITE_BOOL("abort")
|
|
|
|
OPT_WRITE_BOOL("abort_conf")
|
2019-05-01 04:54:00 +08:00
|
|
|
OPT_WRITE_BOOL("confirm_conf")
|
2018-03-15 11:06:04 +08:00
|
|
|
OPT_WRITE_BOOL("retain")
|
|
|
|
OPT_WRITE_CHAR_P("dss")
|
|
|
|
OPT_WRITE_UNSIGNED("narenas")
|
|
|
|
OPT_WRITE_CHAR_P("percpu_arena")
|
2019-01-25 08:15:04 +08:00
|
|
|
OPT_WRITE_SIZE_T("oversize_threshold")
|
2020-08-15 04:36:41 +08:00
|
|
|
OPT_WRITE_BOOL("hpa")
|
2020-09-05 06:22:47 +08:00
|
|
|
OPT_WRITE_SIZE_T("hpa_slab_max_alloc")
|
2020-10-17 04:14:59 +08:00
|
|
|
OPT_WRITE_SIZE_T("hpa_sec_max_alloc")
|
|
|
|
OPT_WRITE_SIZE_T("hpa_sec_max_bytes")
|
|
|
|
OPT_WRITE_SIZE_T("hpa_sec_nshards")
|
2018-03-15 11:06:04 +08:00
|
|
|
OPT_WRITE_CHAR_P("metadata_thp")
|
|
|
|
OPT_WRITE_BOOL_MUTABLE("background_thread", "background_thread")
|
|
|
|
OPT_WRITE_SSIZE_T_MUTABLE("dirty_decay_ms", "arenas.dirty_decay_ms")
|
|
|
|
OPT_WRITE_SSIZE_T_MUTABLE("muzzy_decay_ms", "arenas.muzzy_decay_ms")
|
2018-06-05 02:06:23 +08:00
|
|
|
OPT_WRITE_SIZE_T("lg_extent_max_active_fit")
|
2018-03-15 11:06:04 +08:00
|
|
|
OPT_WRITE_CHAR_P("junk")
|
|
|
|
OPT_WRITE_BOOL("zero")
|
|
|
|
OPT_WRITE_BOOL("utrace")
|
|
|
|
OPT_WRITE_BOOL("xmalloc")
|
|
|
|
OPT_WRITE_BOOL("tcache")
|
|
|
|
OPT_WRITE_SSIZE_T("lg_tcache_max")
|
2020-05-14 01:36:27 +08:00
|
|
|
OPT_WRITE_UNSIGNED("tcache_nslots_small_min")
|
|
|
|
OPT_WRITE_UNSIGNED("tcache_nslots_small_max")
|
|
|
|
OPT_WRITE_UNSIGNED("tcache_nslots_large")
|
|
|
|
OPT_WRITE_SSIZE_T("lg_tcache_nslots_mul")
|
|
|
|
OPT_WRITE_SIZE_T("tcache_gc_incr_bytes")
|
|
|
|
OPT_WRITE_SIZE_T("tcache_gc_delay_bytes")
|
2020-05-14 06:32:18 +08:00
|
|
|
OPT_WRITE_UNSIGNED("lg_tcache_flush_small_div")
|
|
|
|
OPT_WRITE_UNSIGNED("lg_tcache_flush_large_div")
|
2018-03-15 11:06:04 +08:00
|
|
|
OPT_WRITE_CHAR_P("thp")
|
|
|
|
OPT_WRITE_BOOL("prof")
|
|
|
|
OPT_WRITE_CHAR_P("prof_prefix")
|
|
|
|
OPT_WRITE_BOOL_MUTABLE("prof_active", "prof.active")
|
|
|
|
OPT_WRITE_BOOL_MUTABLE("prof_thread_active_init",
|
|
|
|
"prof.thread_active_init")
|
|
|
|
OPT_WRITE_SSIZE_T_MUTABLE("lg_prof_sample", "prof.lg_sample")
|
|
|
|
OPT_WRITE_BOOL("prof_accum")
|
|
|
|
OPT_WRITE_SSIZE_T("lg_prof_interval")
|
|
|
|
OPT_WRITE_BOOL("prof_gdump")
|
|
|
|
OPT_WRITE_BOOL("prof_final")
|
|
|
|
OPT_WRITE_BOOL("prof_leak")
|
|
|
|
OPT_WRITE_BOOL("stats_print")
|
|
|
|
OPT_WRITE_CHAR_P("stats_print_opts")
|
2020-01-14 14:29:17 +08:00
|
|
|
OPT_WRITE_BOOL("stats_print")
|
|
|
|
OPT_WRITE_CHAR_P("stats_print_opts")
|
|
|
|
OPT_WRITE_INT64("stats_interval")
|
|
|
|
OPT_WRITE_CHAR_P("stats_interval_opts")
|
2019-09-24 08:56:19 +08:00
|
|
|
OPT_WRITE_CHAR_P("zero_realloc")
|
2018-03-02 09:38:15 +08:00
|
|
|
|
|
|
|
emitter_dict_end(emitter);
|
|
|
|
|
|
|
|
#undef OPT_WRITE
|
|
|
|
#undef OPT_WRITE_MUTABLE
|
2010-10-24 09:37:06 +08:00
|
|
|
#undef OPT_WRITE_BOOL
|
2014-10-04 14:25:30 +08:00
|
|
|
#undef OPT_WRITE_BOOL_MUTABLE
|
2017-12-15 03:14:08 +08:00
|
|
|
#undef OPT_WRITE_UNSIGNED
|
2010-10-24 09:37:06 +08:00
|
|
|
#undef OPT_WRITE_SSIZE_T
|
2017-12-15 03:14:08 +08:00
|
|
|
#undef OPT_WRITE_SSIZE_T_MUTABLE
|
2010-10-24 09:37:06 +08:00
|
|
|
#undef OPT_WRITE_CHAR_P
|
2010-01-17 01:53:50 +08:00
|
|
|
|
2018-03-02 10:19:25 +08:00
|
|
|
/* prof. */
|
|
|
|
if (config_prof) {
|
|
|
|
emitter_dict_begin(emitter, "prof", "Profiling settings");
|
|
|
|
|
|
|
|
CTL_GET("prof.thread_active_init", &bv, bool);
|
|
|
|
emitter_kv(emitter, "thread_active_init",
|
2018-03-15 09:36:12 +08:00
|
|
|
"prof.thread_active_init", emitter_type_bool, &bv);
|
2018-03-02 10:19:25 +08:00
|
|
|
|
|
|
|
CTL_GET("prof.active", &bv, bool);
|
|
|
|
emitter_kv(emitter, "active", "prof.active", emitter_type_bool,
|
|
|
|
&bv);
|
|
|
|
|
|
|
|
CTL_GET("prof.gdump", &bv, bool);
|
|
|
|
emitter_kv(emitter, "gdump", "prof.gdump", emitter_type_bool,
|
|
|
|
&bv);
|
|
|
|
|
|
|
|
CTL_GET("prof.interval", &u64v, uint64_t);
|
|
|
|
emitter_kv(emitter, "interval", "prof.interval",
|
|
|
|
emitter_type_uint64, &u64v);
|
|
|
|
|
|
|
|
CTL_GET("prof.lg_sample", &ssv, ssize_t);
|
|
|
|
emitter_kv(emitter, "lg_sample", "prof.lg_sample",
|
|
|
|
emitter_type_ssize, &ssv);
|
|
|
|
|
|
|
|
emitter_dict_end(emitter); /* Close "prof". */
|
|
|
|
}
|
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
/* arenas. */
|
2018-03-02 10:02:42 +08:00
|
|
|
/*
|
|
|
|
* The json output sticks arena info into an "arenas" dict; the table
|
|
|
|
* output puts them at the top-level.
|
|
|
|
*/
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "arenas");
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("arenas.narenas", &uv, unsigned);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_kv(emitter, "narenas", "Arenas", emitter_type_unsigned, &uv);
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
/*
|
|
|
|
* Decay settings are emitted only in json mode; in table mode, they're
|
|
|
|
* emitted as notes with the opt output, above.
|
|
|
|
*/
|
|
|
|
CTL_GET("arenas.dirty_decay_ms", &ssv, ssize_t);
|
|
|
|
emitter_json_kv(emitter, "dirty_decay_ms", emitter_type_ssize, &ssv);
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
CTL_GET("arenas.muzzy_decay_ms", &ssv, ssize_t);
|
|
|
|
emitter_json_kv(emitter, "muzzy_decay_ms", emitter_type_ssize, &ssv);
|
Implement two-phase decay-based purging.
Split decay-based purging into two phases, the first of which uses lazy
purging to convert dirty pages to "muzzy", and the second of which uses
forced purging, decommit, or unmapping to convert pages to clean or
destroy them altogether. Not all operating systems support lazy
purging, yet the application may provide extent hooks that implement
lazy purging, so care must be taken to dynamically omit the first phase
when necessary.
The mallctl interfaces change as follows:
- opt.decay_time --> opt.{dirty,muzzy}_decay_time
- arena.<i>.decay_time --> arena.<i>.{dirty,muzzy}_decay_time
- arenas.decay_time --> arenas.{dirty,muzzy}_decay_time
- stats.arenas.<i>.pdirty --> stats.arenas.<i>.p{dirty,muzzy}
- stats.arenas.<i>.{npurge,nmadvise,purged} -->
stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged}
This resolves #521.
2017-03-09 14:42:57 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("arenas.quantum", &sv, size_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_kv(emitter, "quantum", "Quantum size", emitter_type_size, &sv);
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("arenas.page", &sv, size_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_kv(emitter, "page", "Page size", emitter_type_size, &sv);
|
2012-04-02 22:04:34 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
if (je_mallctl("arenas.tcache_max", (void *)&sv, &ssz, NULL, 0) == 0) {
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_kv(emitter, "tcache_max",
|
|
|
|
"Maximum thread-cached size class", emitter_type_size, &sv);
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
unsigned nbins;
|
|
|
|
CTL_GET("arenas.nbins", &nbins, unsigned);
|
|
|
|
emitter_kv(emitter, "nbins", "Number of bin size classes",
|
|
|
|
emitter_type_unsigned, &nbins);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
unsigned nhbins;
|
|
|
|
CTL_GET("arenas.nhbins", &nhbins, unsigned);
|
|
|
|
emitter_kv(emitter, "nhbins", "Number of thread-cache bin size classes",
|
|
|
|
emitter_type_unsigned, &nhbins);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
/*
|
|
|
|
* We do enough mallctls in a loop that we actually want to omit them
|
|
|
|
* (not just omit the printing).
|
|
|
|
*/
|
2019-08-10 01:19:51 +08:00
|
|
|
if (emitter_outputs_json(emitter)) {
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_kv_begin(emitter, "bin");
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t arenas_bin_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(arenas_bin_mib, 0, "arenas.bin");
|
2018-03-02 10:02:42 +08:00
|
|
|
for (unsigned i = 0; i < nbins; i++) {
|
2020-12-18 06:01:56 +08:00
|
|
|
arenas_bin_mib[2] = i;
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_begin(emitter);
|
2010-03-02 12:15:26 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "size", &sv, size_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_json_kv(emitter, "size", emitter_type_size,
|
|
|
|
&sv);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "nregs", &u32v, uint32_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_json_kv(emitter, "nregs", emitter_type_uint32,
|
|
|
|
&u32v);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "slab_size", &sv, size_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_json_kv(emitter, "slab_size", emitter_type_size,
|
|
|
|
&sv);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_bin_mib, 3, "nshards", &u32v, uint32_t);
|
2018-11-22 03:17:31 +08:00
|
|
|
emitter_json_kv(emitter, "nshards", emitter_type_uint32,
|
|
|
|
&u32v);
|
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_end(emitter); /* Close "bin". */
|
2018-03-02 10:02:42 +08:00
|
|
|
}
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-02 10:02:42 +08:00
|
|
|
unsigned nlextents;
|
|
|
|
CTL_GET("arenas.nlextents", &nlextents, unsigned);
|
|
|
|
emitter_kv(emitter, "nlextents", "Number of large size classes",
|
|
|
|
emitter_type_unsigned, &nlextents);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2019-08-10 01:19:51 +08:00
|
|
|
if (emitter_outputs_json(emitter)) {
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_kv_begin(emitter, "lextent");
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t arenas_lextent_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(arenas_lextent_mib, 0, "arenas.lextent");
|
2018-03-02 10:02:42 +08:00
|
|
|
for (unsigned i = 0; i < nlextents; i++) {
|
2020-12-18 06:01:56 +08:00
|
|
|
arenas_lextent_mib[2] = i;
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_begin(emitter);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
CTL_LEAF(arenas_lextent_mib, 3, "size", &sv, size_t);
|
2018-03-02 10:02:42 +08:00
|
|
|
emitter_json_kv(emitter, "size", emitter_type_size,
|
|
|
|
&sv);
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2010-02-12 05:19:21 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_array_end(emitter); /* Close "lextent". */
|
2018-03-02 10:02:42 +08:00
|
|
|
}
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "arenas" */
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
|
|
|
|
2020-12-18 04:04:07 +08:00
|
|
|
JEMALLOC_COLD
|
2016-11-01 13:30:49 +08:00
|
|
|
static void
|
2018-03-03 03:57:13 +08:00
|
|
|
stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
2020-09-05 03:01:52 +08:00
|
|
|
bool unmerged, bool bins, bool large, bool mutex, bool extents, bool hpa) {
|
2018-03-03 03:57:13 +08:00
|
|
|
/*
|
|
|
|
* These should be deleted. We keep them around for a while, to aid in
|
|
|
|
* the transition to the emitter code.
|
|
|
|
*/
|
2017-08-26 04:24:49 +08:00
|
|
|
size_t allocated, active, metadata, metadata_thp, resident, mapped,
|
|
|
|
retained;
|
2017-05-13 03:30:33 +08:00
|
|
|
size_t num_background_threads;
|
2019-10-27 02:04:46 +08:00
|
|
|
size_t zero_reallocs;
|
2017-05-13 03:30:33 +08:00
|
|
|
uint64_t background_thread_num_runs, background_thread_run_interval;
|
2016-11-01 13:30:49 +08:00
|
|
|
|
|
|
|
CTL_GET("stats.allocated", &allocated, size_t);
|
|
|
|
CTL_GET("stats.active", &active, size_t);
|
|
|
|
CTL_GET("stats.metadata", &metadata, size_t);
|
2017-08-26 04:24:49 +08:00
|
|
|
CTL_GET("stats.metadata_thp", &metadata_thp, size_t);
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("stats.resident", &resident, size_t);
|
|
|
|
CTL_GET("stats.mapped", &mapped, size_t);
|
|
|
|
CTL_GET("stats.retained", &retained, size_t);
|
2017-03-12 12:28:31 +08:00
|
|
|
|
2019-10-27 02:04:46 +08:00
|
|
|
CTL_GET("stats.zero_reallocs", &zero_reallocs, size_t);
|
|
|
|
|
2017-05-13 03:30:33 +08:00
|
|
|
if (have_background_thread) {
|
|
|
|
CTL_GET("stats.background_thread.num_threads",
|
|
|
|
&num_background_threads, size_t);
|
|
|
|
CTL_GET("stats.background_thread.num_runs",
|
|
|
|
&background_thread_num_runs, uint64_t);
|
|
|
|
CTL_GET("stats.background_thread.run_interval",
|
|
|
|
&background_thread_run_interval, uint64_t);
|
|
|
|
} else {
|
|
|
|
num_background_threads = 0;
|
|
|
|
background_thread_num_runs = 0;
|
|
|
|
background_thread_run_interval = 0;
|
|
|
|
}
|
|
|
|
|
2018-03-03 05:12:47 +08:00
|
|
|
/* Generic global stats. */
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "stats");
|
2018-03-03 05:12:47 +08:00
|
|
|
emitter_json_kv(emitter, "allocated", emitter_type_size, &allocated);
|
|
|
|
emitter_json_kv(emitter, "active", emitter_type_size, &active);
|
|
|
|
emitter_json_kv(emitter, "metadata", emitter_type_size, &metadata);
|
|
|
|
emitter_json_kv(emitter, "metadata_thp", emitter_type_size,
|
|
|
|
&metadata_thp);
|
|
|
|
emitter_json_kv(emitter, "resident", emitter_type_size, &resident);
|
|
|
|
emitter_json_kv(emitter, "mapped", emitter_type_size, &mapped);
|
|
|
|
emitter_json_kv(emitter, "retained", emitter_type_size, &retained);
|
2019-10-27 02:04:46 +08:00
|
|
|
emitter_json_kv(emitter, "zero_reallocs", emitter_type_size,
|
|
|
|
&zero_reallocs);
|
2018-03-03 05:12:47 +08:00
|
|
|
|
|
|
|
emitter_table_printf(emitter, "Allocated: %zu, active: %zu, "
|
|
|
|
"metadata: %zu (n_thp %zu), resident: %zu, mapped: %zu, "
|
|
|
|
"retained: %zu\n", allocated, active, metadata, metadata_thp,
|
|
|
|
resident, mapped, retained);
|
|
|
|
|
2019-10-27 02:04:46 +08:00
|
|
|
/* Strange behaviors */
|
|
|
|
emitter_table_printf(emitter,
|
|
|
|
"Count of realloc(non-null-ptr, 0) calls: %zu\n", zero_reallocs);
|
|
|
|
|
2018-03-03 05:12:47 +08:00
|
|
|
/* Background thread stats. */
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "background_thread");
|
2018-03-03 05:12:47 +08:00
|
|
|
emitter_json_kv(emitter, "num_threads", emitter_type_size,
|
|
|
|
&num_background_threads);
|
|
|
|
emitter_json_kv(emitter, "num_runs", emitter_type_uint64,
|
|
|
|
&background_thread_num_runs);
|
|
|
|
emitter_json_kv(emitter, "run_interval", emitter_type_uint64,
|
|
|
|
&background_thread_run_interval);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "background_thread". */
|
2018-03-03 05:12:47 +08:00
|
|
|
|
|
|
|
emitter_table_printf(emitter, "Background threads: %zu, "
|
|
|
|
"num_runs: %"FMTu64", run_interval: %"FMTu64" ns\n",
|
|
|
|
num_background_threads, background_thread_num_runs,
|
|
|
|
background_thread_run_interval);
|
2017-05-13 03:30:33 +08:00
|
|
|
|
2018-03-03 07:15:19 +08:00
|
|
|
if (mutex) {
|
|
|
|
emitter_row_t row;
|
|
|
|
emitter_col_t name;
|
|
|
|
emitter_col_t col64[mutex_prof_num_uint64_t_counters];
|
|
|
|
emitter_col_t col32[mutex_prof_num_uint32_t_counters];
|
2018-12-11 03:29:44 +08:00
|
|
|
uint64_t uptime;
|
2018-03-03 07:15:19 +08:00
|
|
|
|
2018-03-07 10:50:53 +08:00
|
|
|
emitter_row_init(&row);
|
|
|
|
mutex_stats_init_cols(&row, "", &name, col64, col32);
|
2018-03-03 07:15:19 +08:00
|
|
|
|
|
|
|
emitter_table_row(emitter, &row);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "mutexes");
|
2018-03-03 07:15:19 +08:00
|
|
|
|
2018-12-11 03:29:44 +08:00
|
|
|
CTL_M2_GET("stats.arenas.0.uptime", 0, &uptime, uint64_t);
|
|
|
|
|
2020-12-18 06:01:56 +08:00
|
|
|
size_t stats_mutexes_mib[CTL_MAX_DEPTH];
|
|
|
|
CTL_LEAF_PREPARE(stats_mutexes_mib, 0, "stats.mutexes");
|
2018-03-03 07:15:19 +08:00
|
|
|
for (int i = 0; i < mutex_prof_num_global_mutexes; i++) {
|
2020-12-18 06:01:56 +08:00
|
|
|
mutex_stats_read_global(stats_mutexes_mib, 2,
|
|
|
|
global_mutex_names[i], &name, col64, col32, uptime);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, global_mutex_names[i]);
|
2018-03-03 07:15:19 +08:00
|
|
|
mutex_stats_emit(emitter, &row, col64, col32);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2017-03-12 12:28:31 +08:00
|
|
|
}
|
2018-03-03 07:15:19 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "mutexes". */
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
2010-01-17 01:53:50 +08:00
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "stats". */
|
2018-03-03 05:12:47 +08:00
|
|
|
|
2017-01-04 09:21:59 +08:00
|
|
|
if (merged || destroyed || unmerged) {
|
2016-11-01 13:30:49 +08:00
|
|
|
unsigned narenas;
|
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "stats.arenas");
|
2010-01-25 09:21:47 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
CTL_GET("arenas.narenas", &narenas, unsigned);
|
2018-03-06 04:58:24 +08:00
|
|
|
size_t mib[3];
|
|
|
|
size_t miblen = sizeof(mib) / sizeof(size_t);
|
|
|
|
size_t sz;
|
|
|
|
VARIABLE_ARRAY(bool, initialized, narenas);
|
|
|
|
bool destroyed_initialized;
|
|
|
|
unsigned i, j, ninitialized;
|
|
|
|
|
|
|
|
xmallctlnametomib("arena.0.initialized", mib, &miblen);
|
|
|
|
for (i = ninitialized = 0; i < narenas; i++) {
|
|
|
|
mib[1] = i;
|
2017-01-04 09:21:59 +08:00
|
|
|
sz = sizeof(bool);
|
2018-03-06 04:58:24 +08:00
|
|
|
xmallctlbymib(mib, miblen, &initialized[i], &sz,
|
2017-01-04 09:21:59 +08:00
|
|
|
NULL, 0);
|
2018-03-06 04:58:24 +08:00
|
|
|
if (initialized[i]) {
|
|
|
|
ninitialized++;
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
2018-03-06 04:58:24 +08:00
|
|
|
}
|
|
|
|
mib[1] = MALLCTL_ARENAS_DESTROYED;
|
|
|
|
sz = sizeof(bool);
|
|
|
|
xmallctlbymib(mib, miblen, &destroyed_initialized, &sz,
|
|
|
|
NULL, 0);
|
|
|
|
|
|
|
|
/* Merged stats. */
|
|
|
|
if (merged && (ninitialized > 1 || !unmerged)) {
|
|
|
|
/* Print merged arena stats. */
|
|
|
|
emitter_table_printf(emitter, "Merged arenas stats:\n");
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "merged");
|
2018-03-06 05:03:22 +08:00
|
|
|
stats_arena_print(emitter, MALLCTL_ARENAS_ALL, bins,
|
2020-09-05 03:01:52 +08:00
|
|
|
large, mutex, extents, hpa);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "merged". */
|
2018-03-06 04:58:24 +08:00
|
|
|
}
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-06 04:58:24 +08:00
|
|
|
/* Destroyed stats. */
|
|
|
|
if (destroyed_initialized && destroyed) {
|
|
|
|
/* Print destroyed arena stats. */
|
|
|
|
emitter_table_printf(emitter,
|
|
|
|
"Destroyed arenas stats:\n");
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter, "destroyed");
|
2018-03-06 05:03:22 +08:00
|
|
|
stats_arena_print(emitter, MALLCTL_ARENAS_DESTROYED,
|
2020-09-05 03:01:52 +08:00
|
|
|
bins, large, mutex, extents, hpa);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "destroyed". */
|
2018-03-06 04:58:24 +08:00
|
|
|
}
|
2017-01-04 09:21:59 +08:00
|
|
|
|
2018-03-06 04:58:24 +08:00
|
|
|
/* Unmerged stats. */
|
|
|
|
if (unmerged) {
|
|
|
|
for (i = j = 0; i < narenas; i++) {
|
|
|
|
if (initialized[i]) {
|
|
|
|
char arena_ind_str[20];
|
|
|
|
malloc_snprintf(arena_ind_str,
|
|
|
|
sizeof(arena_ind_str), "%u", i);
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(emitter,
|
2018-03-06 04:58:24 +08:00
|
|
|
arena_ind_str);
|
|
|
|
emitter_table_printf(emitter,
|
|
|
|
"arenas[%s]:\n", arena_ind_str);
|
2018-03-06 05:03:22 +08:00
|
|
|
stats_arena_print(emitter, i, bins,
|
2020-09-05 03:01:52 +08:00
|
|
|
large, mutex, extents, hpa);
|
2018-03-06 04:58:24 +08:00
|
|
|
/* Close "<arena-ind>". */
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter);
|
2010-01-28 05:10:55 +08:00
|
|
|
}
|
2010-01-25 09:21:47 +08:00
|
|
|
}
|
2010-01-18 09:35:19 +08:00
|
|
|
}
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(emitter); /* Close "stats.arenas". */
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
|
|
|
}
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
void
|
2020-04-18 05:49:20 +08:00
|
|
|
stats_print(write_cb_t *write_cb, void *cbopaque, const char *opts) {
|
2016-11-01 13:30:49 +08:00
|
|
|
int err;
|
|
|
|
uint64_t epoch;
|
|
|
|
size_t u64sz;
|
2017-05-28 06:35:36 +08:00
|
|
|
#define OPTION(o, v, d, s) bool v = d;
|
|
|
|
STATS_PRINT_OPTIONS
|
|
|
|
#undef OPTION
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
/*
|
|
|
|
* Refresh stats, in case mallctl() was called by the application.
|
|
|
|
*
|
|
|
|
* Check for OOM here, since refreshing the ctl cache can trigger
|
|
|
|
* allocation. In practice, none of the subsequent mallctl()-related
|
|
|
|
* calls in this function will cause OOM if this one succeeds.
|
|
|
|
* */
|
|
|
|
epoch = 1;
|
|
|
|
u64sz = sizeof(uint64_t);
|
2016-11-16 07:01:03 +08:00
|
|
|
err = je_mallctl("epoch", (void *)&epoch, &u64sz, (void *)&epoch,
|
|
|
|
sizeof(uint64_t));
|
2016-11-01 13:30:49 +08:00
|
|
|
if (err != 0) {
|
|
|
|
if (err == EAGAIN) {
|
|
|
|
malloc_write("<jemalloc>: Memory allocation failure in "
|
|
|
|
"mallctl(\"epoch\", ...)\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", "
|
|
|
|
"...)\n");
|
|
|
|
abort();
|
|
|
|
}
|
2010-01-28 05:10:55 +08:00
|
|
|
|
2016-11-01 13:30:49 +08:00
|
|
|
if (opts != NULL) {
|
2017-05-28 06:35:36 +08:00
|
|
|
for (unsigned i = 0; opts[i] != '\0'; i++) {
|
2016-11-01 13:30:49 +08:00
|
|
|
switch (opts[i]) {
|
2017-05-28 06:35:36 +08:00
|
|
|
#define OPTION(o, v, d, s) case o: v = s; break;
|
|
|
|
STATS_PRINT_OPTIONS
|
|
|
|
#undef OPTION
|
2016-11-01 13:30:49 +08:00
|
|
|
default:;
|
2010-01-17 01:53:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-01 13:30:49 +08:00
|
|
|
|
2018-03-02 09:29:58 +08:00
|
|
|
emitter_t emitter;
|
|
|
|
emitter_init(&emitter,
|
2019-08-10 01:19:51 +08:00
|
|
|
json ? emitter_output_json_compact : emitter_output_table,
|
|
|
|
write_cb, cbopaque);
|
2018-03-02 09:29:58 +08:00
|
|
|
emitter_begin(&emitter);
|
|
|
|
emitter_table_printf(&emitter, "___ Begin jemalloc statistics ___\n");
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_kv_begin(&emitter, "jemalloc");
|
2018-03-02 09:29:58 +08:00
|
|
|
|
2016-12-24 03:15:44 +08:00
|
|
|
if (general) {
|
2018-03-02 11:01:05 +08:00
|
|
|
stats_general_print(&emitter);
|
|
|
|
}
|
2016-11-01 13:30:49 +08:00
|
|
|
if (config_stats) {
|
2018-03-03 03:57:13 +08:00
|
|
|
stats_print_helper(&emitter, merged, destroyed, unmerged,
|
2020-09-05 03:01:52 +08:00
|
|
|
bins, large, mutex, extents, hpa);
|
2016-11-01 13:30:49 +08:00
|
|
|
}
|
|
|
|
|
2018-07-06 01:31:43 +08:00
|
|
|
emitter_json_object_end(&emitter); /* Closes the "jemalloc" dict. */
|
2018-03-02 09:29:58 +08:00
|
|
|
emitter_table_printf(&emitter, "--- End jemalloc statistics ---\n");
|
|
|
|
emitter_end(&emitter);
|
2010-01-17 01:53:50 +08:00
|
|
|
}
|
2020-01-14 14:29:17 +08:00
|
|
|
|
|
|
|
uint64_t
|
2020-04-16 01:49:08 +08:00
|
|
|
stats_interval_new_event_wait(tsd_t *tsd) {
|
2020-01-14 14:29:17 +08:00
|
|
|
return stats_interval_accum_batch;
|
|
|
|
}
|
|
|
|
|
2020-04-17 04:33:56 +08:00
|
|
|
uint64_t
|
|
|
|
stats_interval_postponed_event_wait(tsd_t *tsd) {
|
|
|
|
return TE_MIN_START_WAIT;
|
|
|
|
}
|
|
|
|
|
2020-04-18 01:38:06 +08:00
|
|
|
void
|
|
|
|
stats_interval_event_handler(tsd_t *tsd, uint64_t elapsed) {
|
|
|
|
assert(elapsed > 0 && elapsed != TE_INVALID_ELAPSED);
|
|
|
|
if (counter_accum(tsd_tsdn(tsd), &stats_interval_accumulated,
|
|
|
|
elapsed)) {
|
|
|
|
je_malloc_stats_print(NULL, NULL, opt_stats_interval_opts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-14 14:29:17 +08:00
|
|
|
bool
|
|
|
|
stats_boot(void) {
|
|
|
|
uint64_t stats_interval;
|
|
|
|
if (opt_stats_interval < 0) {
|
|
|
|
assert(opt_stats_interval == -1);
|
|
|
|
stats_interval = 0;
|
|
|
|
stats_interval_accum_batch = 0;
|
|
|
|
} else{
|
|
|
|
/* See comments in stats.h */
|
|
|
|
stats_interval = (opt_stats_interval > 0) ?
|
|
|
|
opt_stats_interval : 1;
|
|
|
|
uint64_t batch = stats_interval >>
|
|
|
|
STATS_INTERVAL_ACCUM_LG_BATCH_SIZE;
|
|
|
|
if (batch > STATS_INTERVAL_ACCUM_BATCH_MAX) {
|
|
|
|
batch = STATS_INTERVAL_ACCUM_BATCH_MAX;
|
|
|
|
} else if (batch == 0) {
|
|
|
|
batch = 1;
|
|
|
|
}
|
|
|
|
stats_interval_accum_batch = batch;
|
|
|
|
}
|
|
|
|
|
|
|
|
return counter_accum_init(&stats_interval_accumulated, stats_interval);
|
|
|
|
}
|
2020-04-16 06:09:32 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
stats_prefork(tsdn_t *tsdn) {
|
|
|
|
counter_prefork(tsdn, &stats_interval_accumulated);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
stats_postfork_parent(tsdn_t *tsdn) {
|
|
|
|
counter_postfork_parent(tsdn, &stats_interval_accumulated);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
stats_postfork_child(tsdn_t *tsdn) {
|
|
|
|
counter_postfork_child(tsdn, &stats_interval_accumulated);
|
|
|
|
}
|