mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-18 14:47:18 +03:00
Expose stats table columns in JSON output and simplify code
This commit is contained in:
parent
e1b5edcc62
commit
82906161eb
4 changed files with 163 additions and 217 deletions
|
|
@ -591,13 +591,12 @@ emitter_sparse_row(emitter_t *emitter, emitter_row_t *row, bool is_gap) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Descriptor-driven column tables. A descriptor array defines table order;
|
||||
* callers provide a separate index array when JSON requires a different
|
||||
* subset or ordering. The getter lets one engine serve different row types
|
||||
* while keeping derived values (rates, utilization, and so on) with the
|
||||
* table-specific code. A column is active when all its required_flags are
|
||||
* present in the active_flags supplied by the caller; the emitter assigns no
|
||||
* domain-specific meaning to those bits.
|
||||
* Descriptor-driven column tables. A descriptor array defines table and JSON
|
||||
* order; columns with a NULL json_key are table-only. The getter lets one
|
||||
* engine serve different row types while keeping derived values (rates,
|
||||
* utilization, and so on) with the table-specific code. A column is active
|
||||
* when all its required_flags are present in the active_flags supplied by the
|
||||
* caller; the emitter assigns no domain-specific meaning to those bits.
|
||||
*/
|
||||
typedef struct emitter_col_desc_s emitter_col_desc_t;
|
||||
struct emitter_col_desc_s {
|
||||
|
|
@ -666,17 +665,18 @@ emitter_col_table_fill(const emitter_col_desc_t *descs, size_t ndescs,
|
|||
static inline void
|
||||
emitter_col_table_emit_json(emitter_t *emitter,
|
||||
const emitter_col_desc_t *descs, size_t ndescs, unsigned active_flags,
|
||||
emitter_col_t *cols, const unsigned *json_order, size_t json_order_len) {
|
||||
for (size_t i = 0; i < json_order_len; i++) {
|
||||
unsigned col_ind = json_order[i];
|
||||
assert(col_ind < ndescs);
|
||||
const emitter_col_desc_t *desc = &descs[col_ind];
|
||||
emitter_col_t *cols) {
|
||||
for (size_t i = 0; i < ndescs; i++) {
|
||||
const emitter_col_desc_t *desc = &descs[i];
|
||||
if (!emitter_col_desc_active(desc, active_flags)) {
|
||||
continue;
|
||||
}
|
||||
assert(desc->json_key != NULL);
|
||||
emitter_json_kv(emitter, desc->json_key, cols[col_ind].type,
|
||||
(const void *)&cols[col_ind].bool_val);
|
||||
if (desc->json_key != NULL) {
|
||||
emitter_type_t json_type = cols[i].type == emitter_type_title
|
||||
? emitter_type_string : cols[i].type;
|
||||
emitter_json_kv(emitter, desc->json_key, json_type,
|
||||
(const void *)&cols[i].bool_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
246
src/stats.c
246
src/stats.c
|
|
@ -782,54 +782,27 @@ stats_bin_col_get_util(const void *vrow, emitter_col_t *col) {
|
|||
col->str_val = row->util;
|
||||
}
|
||||
|
||||
enum {
|
||||
BIN_COL_SIZE,
|
||||
BIN_COL_IND,
|
||||
BIN_COL_ALLOCATED,
|
||||
BIN_COL_NMALLOC,
|
||||
BIN_COL_NMALLOC_PS,
|
||||
BIN_COL_NDALLOC,
|
||||
BIN_COL_NDALLOC_PS,
|
||||
BIN_COL_NREQUESTS,
|
||||
BIN_COL_NREQUESTS_PS,
|
||||
BIN_COL_PROF_LIVE_REQUESTED,
|
||||
BIN_COL_PROF_LIVE_COUNT,
|
||||
BIN_COL_PROF_ACCUM_REQUESTED,
|
||||
BIN_COL_PROF_ACCUM_COUNT,
|
||||
BIN_COL_NSHARDS,
|
||||
BIN_COL_CURREGS,
|
||||
BIN_COL_CURSLABS,
|
||||
BIN_COL_NONFULL_SLABS,
|
||||
BIN_COL_REGS,
|
||||
BIN_COL_PGS,
|
||||
BIN_COL_SPACER,
|
||||
BIN_COL_UTIL,
|
||||
BIN_COL_NFILLS,
|
||||
BIN_COL_NFILLS_PS,
|
||||
BIN_COL_NFLUSHES,
|
||||
BIN_COL_NFLUSHES_PS,
|
||||
BIN_COL_NSLABS,
|
||||
BIN_COL_NRESLABS,
|
||||
BIN_COL_NRESLABS_PS,
|
||||
BIN_COL_COUNT
|
||||
};
|
||||
#define BIN_COL_SIZE 0
|
||||
|
||||
#define BIN_DESC(key, label, width, type, flags, name) \
|
||||
{key, label, emitter_justify_right, width, emitter_type_##type, flags, \
|
||||
stats_bin_col_get_##name}
|
||||
static const emitter_col_desc_t stats_bin_cols[] = {
|
||||
BIN_DESC(NULL, "size", 20, size, STATS_COL_FLAG_NONE, size),
|
||||
BIN_DESC(NULL, "ind", 4, unsigned, STATS_COL_FLAG_NONE, ind),
|
||||
BIN_DESC(NULL, "allocated", 14, size, STATS_COL_FLAG_NONE, allocated),
|
||||
BIN_DESC("size", "size", 20, size, STATS_COL_FLAG_NONE, size),
|
||||
BIN_DESC("ind", "ind", 4, unsigned, STATS_COL_FLAG_NONE, ind),
|
||||
BIN_DESC("allocated", "allocated", 14, size, STATS_COL_FLAG_NONE,
|
||||
allocated),
|
||||
BIN_DESC("nmalloc", "nmalloc", 14, uint64, STATS_COL_FLAG_NONE,
|
||||
nmalloc),
|
||||
BIN_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE, nmalloc_ps),
|
||||
BIN_DESC("nmalloc_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
nmalloc_ps),
|
||||
BIN_DESC("ndalloc", "ndalloc", 14, uint64, STATS_COL_FLAG_NONE,
|
||||
ndalloc),
|
||||
BIN_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE, ndalloc_ps),
|
||||
BIN_DESC("ndalloc_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
ndalloc_ps),
|
||||
BIN_DESC("nrequests", "nrequests", 15, uint64, STATS_COL_FLAG_NONE,
|
||||
nrequests),
|
||||
BIN_DESC(NULL, "(#/sec)", 10, uint64, STATS_COL_FLAG_NONE,
|
||||
BIN_DESC("nrequests_ps", "(#/sec)", 10, uint64, STATS_COL_FLAG_NONE,
|
||||
nrequests_ps),
|
||||
BIN_DESC("prof_live_requested", "prof_live_requested", 21, uint64,
|
||||
STATS_COL_FLAG_PROF, prof_live_requested),
|
||||
|
|
@ -839,48 +812,33 @@ static const emitter_col_desc_t stats_bin_cols[] = {
|
|||
STATS_COL_FLAG_PROF, prof_accum_requested),
|
||||
BIN_DESC("prof_accum_count", "prof_accum_count", 17, uint64,
|
||||
STATS_COL_FLAG_PROF, prof_accum_count),
|
||||
BIN_DESC(NULL, "nshards", 9, unsigned, STATS_COL_FLAG_NONE, nshards),
|
||||
BIN_DESC("nshards", "nshards", 9, unsigned, STATS_COL_FLAG_NONE,
|
||||
nshards),
|
||||
BIN_DESC("curregs", "curregs", 13, size, STATS_COL_FLAG_NONE, curregs),
|
||||
BIN_DESC("curslabs", "curslabs", 13, size, STATS_COL_FLAG_NONE,
|
||||
curslabs),
|
||||
BIN_DESC("nonfull_slabs", "nonfull_slabs", 15, size,
|
||||
STATS_COL_FLAG_NONE,
|
||||
nonfull_slabs),
|
||||
BIN_DESC(NULL, "regs", 5, unsigned, STATS_COL_FLAG_NONE, regs),
|
||||
BIN_DESC(NULL, "pgs", 4, size, STATS_COL_FLAG_NONE, pgs),
|
||||
BIN_DESC("regs", "regs", 5, unsigned, STATS_COL_FLAG_NONE, regs),
|
||||
BIN_DESC("pgs", "pgs", 4, size, STATS_COL_FLAG_NONE, pgs),
|
||||
BIN_DESC(NULL, " ", 1, title, STATS_COL_FLAG_NONE, spacer),
|
||||
BIN_DESC(NULL, "util", 6, title, STATS_COL_FLAG_NONE, util),
|
||||
BIN_DESC("util", "util", 6, title, STATS_COL_FLAG_NONE, util),
|
||||
BIN_DESC("nfills", "nfills", 13, uint64, STATS_COL_FLAG_NONE, nfills),
|
||||
BIN_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE, nfills_ps),
|
||||
BIN_DESC("nfills_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
nfills_ps),
|
||||
BIN_DESC("nflushes", "nflushes", 13, uint64, STATS_COL_FLAG_NONE,
|
||||
nflushes),
|
||||
BIN_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
BIN_DESC("nflushes_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
nflushes_ps),
|
||||
BIN_DESC(NULL, "nslabs", 13, uint64, STATS_COL_FLAG_NONE, nslabs),
|
||||
BIN_DESC("nslabs", "nslabs", 13, uint64, STATS_COL_FLAG_NONE, nslabs),
|
||||
BIN_DESC("nreslabs", "nreslabs", 13, uint64, STATS_COL_FLAG_NONE,
|
||||
nreslabs),
|
||||
BIN_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
BIN_DESC("nreslabs_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
nreslabs_ps),
|
||||
};
|
||||
#undef BIN_DESC
|
||||
_Static_assert(sizeof(stats_bin_cols) / sizeof(stats_bin_cols[0]) ==
|
||||
BIN_COL_COUNT, "stats_bin_cols must match BIN_COL_COUNT");
|
||||
|
||||
static const unsigned stats_bin_json_order[] = {
|
||||
BIN_COL_NMALLOC,
|
||||
BIN_COL_NDALLOC,
|
||||
BIN_COL_CURREGS,
|
||||
BIN_COL_NREQUESTS,
|
||||
BIN_COL_PROF_LIVE_REQUESTED,
|
||||
BIN_COL_PROF_LIVE_COUNT,
|
||||
BIN_COL_PROF_ACCUM_REQUESTED,
|
||||
BIN_COL_PROF_ACCUM_COUNT,
|
||||
BIN_COL_NFILLS,
|
||||
BIN_COL_NFLUSHES,
|
||||
BIN_COL_NRESLABS,
|
||||
BIN_COL_CURSLABS,
|
||||
BIN_COL_NONFULL_SLABS,
|
||||
};
|
||||
#define BIN_COL_COUNT (sizeof(stats_bin_cols) / sizeof(stats_bin_cols[0]))
|
||||
|
||||
static void
|
||||
stats_emit_arena_bin_row(emitter_t *emitter, emitter_row_t *table_row,
|
||||
|
|
@ -892,8 +850,7 @@ stats_emit_arena_bin_row(emitter_t *emitter, emitter_row_t *table_row,
|
|||
stats_bin_cols, BIN_COL_COUNT, active_flags, cols, row);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, stats_bin_cols, BIN_COL_COUNT,
|
||||
active_flags, cols, stats_bin_json_order,
|
||||
sizeof(stats_bin_json_order) / sizeof(stats_bin_json_order[0]));
|
||||
active_flags, cols);
|
||||
if (mutex) {
|
||||
emitter_json_object_kv_begin(emitter, "mutex");
|
||||
mutex_stats_emit(emitter, NULL, mutex64, mutex32);
|
||||
|
|
@ -1068,41 +1025,29 @@ stats_lextent_col_get_allocated(const void *vrow, emitter_col_t *col) {
|
|||
col->size_val = row->lextent->curlextents * row->lextent->lextent_size;
|
||||
}
|
||||
|
||||
enum {
|
||||
LEXTENT_COL_SIZE,
|
||||
LEXTENT_COL_IND,
|
||||
LEXTENT_COL_ALLOCATED,
|
||||
LEXTENT_COL_NMALLOC,
|
||||
LEXTENT_COL_NMALLOC_PS,
|
||||
LEXTENT_COL_NDALLOC,
|
||||
LEXTENT_COL_NDALLOC_PS,
|
||||
LEXTENT_COL_NREQUESTS,
|
||||
LEXTENT_COL_NREQUESTS_PS,
|
||||
LEXTENT_COL_PROF_LIVE_REQUESTED,
|
||||
LEXTENT_COL_PROF_LIVE_COUNT,
|
||||
LEXTENT_COL_PROF_ACCUM_REQUESTED,
|
||||
LEXTENT_COL_PROF_ACCUM_COUNT,
|
||||
LEXTENT_COL_CURLEXTENTS,
|
||||
LEXTENT_COL_COUNT
|
||||
};
|
||||
#define LEXTENT_COL_SIZE 0
|
||||
|
||||
#define LEXTENT_DESC(key, label, width, type, flags, name) \
|
||||
{key, label, emitter_justify_right, width, emitter_type_##type, flags, \
|
||||
stats_lextent_col_get_##name}
|
||||
static const emitter_col_desc_t stats_lextent_cols[] = {
|
||||
LEXTENT_DESC(NULL, "size", 20, size, STATS_COL_FLAG_NONE, size),
|
||||
LEXTENT_DESC(NULL, "ind", 4, unsigned, STATS_COL_FLAG_NONE, ind),
|
||||
LEXTENT_DESC(NULL, "allocated", 13, size, STATS_COL_FLAG_NONE,
|
||||
LEXTENT_DESC("size", "size", 20, size, STATS_COL_FLAG_NONE, size),
|
||||
LEXTENT_DESC("ind", "ind", 4, unsigned, STATS_COL_FLAG_NONE, ind),
|
||||
LEXTENT_DESC("allocated", "allocated", 13, size, STATS_COL_FLAG_NONE,
|
||||
allocated),
|
||||
LEXTENT_DESC(NULL, "nmalloc", 13, uint64, STATS_COL_FLAG_NONE, nmalloc),
|
||||
LEXTENT_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
LEXTENT_DESC("nmalloc", "nmalloc", 13, uint64, STATS_COL_FLAG_NONE,
|
||||
nmalloc),
|
||||
LEXTENT_DESC("nmalloc_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
nmalloc_ps),
|
||||
LEXTENT_DESC(NULL, "ndalloc", 13, uint64, STATS_COL_FLAG_NONE, ndalloc),
|
||||
LEXTENT_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
LEXTENT_DESC("ndalloc", "ndalloc", 13, uint64, STATS_COL_FLAG_NONE,
|
||||
ndalloc),
|
||||
LEXTENT_DESC("ndalloc_ps", "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
ndalloc_ps),
|
||||
LEXTENT_DESC(NULL, "nrequests", 13, uint64, STATS_COL_FLAG_NONE,
|
||||
LEXTENT_DESC("nrequests", "nrequests", 13, uint64,
|
||||
STATS_COL_FLAG_NONE,
|
||||
nrequests),
|
||||
LEXTENT_DESC(NULL, "(#/sec)", 8, uint64, STATS_COL_FLAG_NONE,
|
||||
LEXTENT_DESC("nrequests_ps", "(#/sec)", 8, uint64,
|
||||
STATS_COL_FLAG_NONE,
|
||||
nrequests_ps),
|
||||
LEXTENT_DESC("prof_live_requested", "prof_live_requested", 21, uint64,
|
||||
STATS_COL_FLAG_PROF, prof_live_requested),
|
||||
|
|
@ -1116,16 +1061,8 @@ static const emitter_col_desc_t stats_lextent_cols[] = {
|
|||
STATS_COL_FLAG_NONE, curlextents),
|
||||
};
|
||||
#undef LEXTENT_DESC
|
||||
_Static_assert(sizeof(stats_lextent_cols) / sizeof(stats_lextent_cols[0]) ==
|
||||
LEXTENT_COL_COUNT, "stats_lextent_cols must match LEXTENT_COL_COUNT");
|
||||
|
||||
static const unsigned stats_lextent_json_order[] = {
|
||||
LEXTENT_COL_PROF_LIVE_REQUESTED,
|
||||
LEXTENT_COL_PROF_LIVE_COUNT,
|
||||
LEXTENT_COL_PROF_ACCUM_REQUESTED,
|
||||
LEXTENT_COL_PROF_ACCUM_COUNT,
|
||||
LEXTENT_COL_CURLEXTENTS,
|
||||
};
|
||||
#define LEXTENT_COL_COUNT \
|
||||
(sizeof(stats_lextent_cols) / sizeof(stats_lextent_cols[0]))
|
||||
|
||||
static void
|
||||
stats_emit_arena_lextent_row(emitter_t *emitter, emitter_row_t *table_row,
|
||||
|
|
@ -1134,16 +1071,14 @@ stats_emit_arena_lextent_row(emitter_t *emitter, emitter_row_t *table_row,
|
|||
unsigned active_flags = stats_col_active_flags(prof_stats_on);
|
||||
emitter_col_table_fill(stats_lextent_cols, LEXTENT_COL_COUNT,
|
||||
active_flags, cols, row);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, stats_lextent_cols,
|
||||
LEXTENT_COL_COUNT, active_flags, cols);
|
||||
emitter_json_object_end(emitter);
|
||||
char size_buf[48];
|
||||
stats_size_col_set(&cols[LEXTENT_COL_SIZE], row->lextent->lextent_size,
|
||||
prev_size, size_buf, sizeof(size_buf));
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, stats_lextent_cols,
|
||||
LEXTENT_COL_COUNT, active_flags, cols, stats_lextent_json_order,
|
||||
sizeof(stats_lextent_json_order) /
|
||||
sizeof(stats_lextent_json_order[0]));
|
||||
emitter_table_sparse_row(emitter, table_row, is_gap);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
|
||||
JEMALLOC_COLD
|
||||
|
|
@ -1241,29 +1176,15 @@ stats_extent_col_get_ind(const void *vrow, emitter_col_t *col) {
|
|||
col->unsigned_val = row->ind;
|
||||
}
|
||||
|
||||
enum {
|
||||
EXTENT_COL_SIZE,
|
||||
EXTENT_COL_IND,
|
||||
EXTENT_COL_NDIRTY,
|
||||
EXTENT_COL_DIRTY,
|
||||
EXTENT_COL_NMUZZY,
|
||||
EXTENT_COL_MUZZY,
|
||||
EXTENT_COL_NRETAINED,
|
||||
EXTENT_COL_RETAINED,
|
||||
EXTENT_COL_NPINNED,
|
||||
EXTENT_COL_PINNED,
|
||||
EXTENT_COL_NTOTAL,
|
||||
EXTENT_COL_TOTAL,
|
||||
EXTENT_COL_COUNT
|
||||
};
|
||||
#define EXTENT_COL_SIZE 0
|
||||
|
||||
#define EXTENT_DESC(key, label, name) \
|
||||
{key, label, emitter_justify_right, 13, emitter_type_size, \
|
||||
STATS_COL_FLAG_NONE, stats_extent_col_get_##name}
|
||||
static const emitter_col_desc_t stats_extent_cols[] = {
|
||||
{NULL, "size", emitter_justify_right, 20, emitter_type_size,
|
||||
{"size", "size", emitter_justify_right, 20, emitter_type_size,
|
||||
STATS_COL_FLAG_NONE, stats_extent_col_get_size},
|
||||
{NULL, "ind", emitter_justify_right, 4, emitter_type_unsigned,
|
||||
{"ind", "ind", emitter_justify_right, 4, emitter_type_unsigned,
|
||||
STATS_COL_FLAG_NONE, stats_extent_col_get_ind},
|
||||
EXTENT_DESC("ndirty", "ndirty", ndirty),
|
||||
EXTENT_DESC("dirty_bytes", "dirty", dirty),
|
||||
|
|
@ -1273,23 +1194,12 @@ static const emitter_col_desc_t stats_extent_cols[] = {
|
|||
EXTENT_DESC("retained_bytes", "retained", retained),
|
||||
EXTENT_DESC("npinned", "npinned", npinned),
|
||||
EXTENT_DESC("pinned_bytes", "pinned", pinned),
|
||||
EXTENT_DESC(NULL, "ntotal", ntotal),
|
||||
EXTENT_DESC(NULL, "total", total),
|
||||
EXTENT_DESC("ntotal", "ntotal", ntotal),
|
||||
EXTENT_DESC("total_bytes", "total", total),
|
||||
};
|
||||
#undef EXTENT_DESC
|
||||
_Static_assert(sizeof(stats_extent_cols) / sizeof(stats_extent_cols[0]) ==
|
||||
EXTENT_COL_COUNT, "stats_extent_cols must match EXTENT_COL_COUNT");
|
||||
|
||||
static const unsigned stats_extent_json_order[] = {
|
||||
EXTENT_COL_NDIRTY,
|
||||
EXTENT_COL_NMUZZY,
|
||||
EXTENT_COL_NRETAINED,
|
||||
EXTENT_COL_NPINNED,
|
||||
EXTENT_COL_DIRTY,
|
||||
EXTENT_COL_MUZZY,
|
||||
EXTENT_COL_RETAINED,
|
||||
EXTENT_COL_PINNED,
|
||||
};
|
||||
#define EXTENT_COL_COUNT \
|
||||
(sizeof(stats_extent_cols) / sizeof(stats_extent_cols[0]))
|
||||
|
||||
static void
|
||||
stats_emit_arena_extent_row(emitter_t *emitter, emitter_row_t *table_row,
|
||||
|
|
@ -1297,15 +1207,13 @@ stats_emit_arena_extent_row(emitter_t *emitter, emitter_row_t *table_row,
|
|||
size_t prev_size, bool is_gap) {
|
||||
emitter_col_table_fill(stats_extent_cols, EXTENT_COL_COUNT,
|
||||
STATS_COL_FLAG_NONE, cols, row);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, stats_extent_cols, EXTENT_COL_COUNT,
|
||||
STATS_COL_FLAG_NONE, cols);
|
||||
emitter_json_object_end(emitter);
|
||||
char size_buf[48];
|
||||
stats_size_col_set(&cols[EXTENT_COL_SIZE], row->size, prev_size,
|
||||
size_buf, sizeof(size_buf));
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, stats_extent_cols, EXTENT_COL_COUNT,
|
||||
STATS_COL_FLAG_NONE, cols, stats_extent_json_order,
|
||||
sizeof(stats_extent_json_order) /
|
||||
sizeof(stats_extent_json_order[0]));
|
||||
emitter_json_object_end(emitter);
|
||||
emitter_table_sparse_row(emitter, table_row, is_gap);
|
||||
}
|
||||
|
||||
|
|
@ -1573,26 +1481,15 @@ stats_hpa_slab_col_get_ind(const void *vrow, emitter_col_t *col) {
|
|||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
HPA_SLAB_COL_SIZE,
|
||||
HPA_SLAB_COL_IND,
|
||||
HPA_SLAB_COL_NPAGESLABS_HUGE,
|
||||
HPA_SLAB_COL_NACTIVE_HUGE,
|
||||
HPA_SLAB_COL_NDIRTY_HUGE,
|
||||
HPA_SLAB_COL_NPAGESLABS_NONHUGE,
|
||||
HPA_SLAB_COL_NACTIVE_NONHUGE,
|
||||
HPA_SLAB_COL_NDIRTY_NONHUGE,
|
||||
HPA_SLAB_COL_NRETAINED_NONHUGE,
|
||||
HPA_SLAB_COL_COUNT
|
||||
};
|
||||
#define HPA_SLAB_COL_SIZE 0
|
||||
|
||||
#define HPA_SLAB_DESC(name, width) \
|
||||
{#name, #name, emitter_justify_right, width, emitter_type_size, \
|
||||
STATS_COL_FLAG_NONE, stats_hpa_slab_col_get_##name}
|
||||
static const emitter_col_desc_t stats_hpa_slab_cols[] = {
|
||||
{NULL, "size", emitter_justify_right, 20, emitter_type_size,
|
||||
{"size", "size", emitter_justify_right, 20, emitter_type_size,
|
||||
STATS_COL_FLAG_NONE, stats_hpa_slab_col_get_size},
|
||||
{NULL, "ind", emitter_justify_right, 4, emitter_type_unsigned,
|
||||
{"ind", "ind", emitter_justify_right, 4, emitter_type_unsigned,
|
||||
STATS_COL_FLAG_NONE, stats_hpa_slab_col_get_ind},
|
||||
HPA_SLAB_DESC(npageslabs_huge, 16),
|
||||
HPA_SLAB_DESC(nactive_huge, 16),
|
||||
|
|
@ -1603,20 +1500,8 @@ static const emitter_col_desc_t stats_hpa_slab_cols[] = {
|
|||
HPA_SLAB_DESC(nretained_nonhuge, 20),
|
||||
};
|
||||
#undef HPA_SLAB_DESC
|
||||
_Static_assert(
|
||||
sizeof(stats_hpa_slab_cols) / sizeof(stats_hpa_slab_cols[0]) ==
|
||||
HPA_SLAB_COL_COUNT,
|
||||
"stats_hpa_slab_cols must match HPA_SLAB_COL_COUNT");
|
||||
|
||||
static const unsigned stats_hpa_slab_json_order[] = {
|
||||
HPA_SLAB_COL_NPAGESLABS_HUGE,
|
||||
HPA_SLAB_COL_NACTIVE_HUGE,
|
||||
HPA_SLAB_COL_NDIRTY_HUGE,
|
||||
HPA_SLAB_COL_NPAGESLABS_NONHUGE,
|
||||
HPA_SLAB_COL_NACTIVE_NONHUGE,
|
||||
HPA_SLAB_COL_NDIRTY_NONHUGE,
|
||||
HPA_SLAB_COL_NRETAINED_NONHUGE,
|
||||
};
|
||||
#define HPA_SLAB_COL_COUNT \
|
||||
(sizeof(stats_hpa_slab_cols) / sizeof(stats_hpa_slab_cols[0]))
|
||||
|
||||
static void
|
||||
stats_emit_arena_hpa_slab_row(emitter_t *emitter,
|
||||
|
|
@ -1625,22 +1510,19 @@ stats_emit_arena_hpa_slab_row(emitter_t *emitter,
|
|||
bool sparse, bool is_gap) {
|
||||
emitter_col_table_fill(stats_hpa_slab_cols, HPA_SLAB_COL_COUNT,
|
||||
STATS_COL_FLAG_NONE, cols, row);
|
||||
char size_buf[48];
|
||||
if (row->size_title == NULL) {
|
||||
stats_size_col_set(&cols[HPA_SLAB_COL_SIZE], row->size,
|
||||
row->prev_size, size_buf, sizeof(size_buf));
|
||||
}
|
||||
if (json_key != NULL) {
|
||||
emitter_json_object_kv_begin(emitter, json_key);
|
||||
} else {
|
||||
emitter_json_object_begin(emitter);
|
||||
}
|
||||
emitter_col_table_emit_json(emitter, stats_hpa_slab_cols,
|
||||
HPA_SLAB_COL_COUNT, STATS_COL_FLAG_NONE, cols,
|
||||
stats_hpa_slab_json_order,
|
||||
sizeof(stats_hpa_slab_json_order) /
|
||||
sizeof(stats_hpa_slab_json_order[0]));
|
||||
HPA_SLAB_COL_COUNT, STATS_COL_FLAG_NONE, cols);
|
||||
emitter_json_object_end(emitter);
|
||||
char size_buf[48];
|
||||
if (row->size_title == NULL) {
|
||||
stats_size_col_set(&cols[HPA_SLAB_COL_SIZE], row->size,
|
||||
row->prev_size, size_buf, sizeof(size_buf));
|
||||
}
|
||||
if (sparse) {
|
||||
emitter_table_sparse_row(emitter, table_row, is_gap);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -669,10 +669,11 @@ static const char *sparse_row_table =
|
|||
" ---\n";
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
uint64_t count;
|
||||
uint64_t prof_count;
|
||||
uint64_t requests;
|
||||
size_t size;
|
||||
uint64_t count;
|
||||
uint64_t prof_count;
|
||||
const char *label;
|
||||
uint64_t requests;
|
||||
} col_table_test_row_t;
|
||||
|
||||
#define COL_TABLE_TEST_GETTER(name, member, value_member) \
|
||||
|
|
@ -684,6 +685,7 @@ typedef struct {
|
|||
COL_TABLE_TEST_GETTER(size, size, size_val)
|
||||
COL_TABLE_TEST_GETTER(count, count, uint64_val)
|
||||
COL_TABLE_TEST_GETTER(prof_count, prof_count, uint64_val)
|
||||
COL_TABLE_TEST_GETTER(label, label, str_val)
|
||||
COL_TABLE_TEST_GETTER(requests, requests, uint64_val)
|
||||
#undef COL_TABLE_TEST_GETTER
|
||||
|
||||
|
|
@ -691,6 +693,7 @@ enum {
|
|||
COL_TABLE_TEST_SIZE,
|
||||
COL_TABLE_TEST_COUNT,
|
||||
COL_TABLE_TEST_PROF_COUNT,
|
||||
COL_TABLE_TEST_LABEL,
|
||||
COL_TABLE_TEST_REQUESTS,
|
||||
COL_TABLE_TEST_NCOLS
|
||||
};
|
||||
|
|
@ -704,6 +707,8 @@ static const emitter_col_desc_t col_table_test_descs[] = {
|
|||
0, col_table_test_get_count},
|
||||
{"prof_count", "prof", emitter_justify_right, 6, emitter_type_uint64,
|
||||
COL_TABLE_TEST_FLAG_PROF, col_table_test_get_prof_count},
|
||||
{"label", "label", emitter_justify_right, 7, emitter_type_title, 0,
|
||||
col_table_test_get_label},
|
||||
{"requests", "requests", emitter_justify_right, 10,
|
||||
emitter_type_uint64, 0, col_table_test_get_requests},
|
||||
};
|
||||
|
|
@ -726,15 +731,9 @@ TEST_BEGIN(test_col_desc_flags) {
|
|||
}
|
||||
TEST_END
|
||||
|
||||
static const unsigned col_table_test_json_order[] = {
|
||||
COL_TABLE_TEST_REQUESTS,
|
||||
COL_TABLE_TEST_PROF_COUNT,
|
||||
COL_TABLE_TEST_COUNT,
|
||||
};
|
||||
|
||||
static void
|
||||
emit_col_table(emitter_t *emitter) {
|
||||
col_table_test_row_t value = {42, 7, 100, 9};
|
||||
col_table_test_row_t value = {42, 7, 100, "row", 9};
|
||||
emitter_row_t row, header_row;
|
||||
emitter_col_t cols[COL_TABLE_TEST_NCOLS];
|
||||
emitter_col_t header_cols[COL_TABLE_TEST_NCOLS];
|
||||
|
|
@ -748,9 +747,7 @@ emit_col_table(emitter_t *emitter) {
|
|||
COL_TABLE_TEST_FLAG_PROF, cols, &value);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_col_table_emit_json(emitter, col_table_test_descs,
|
||||
COL_TABLE_TEST_NCOLS, COL_TABLE_TEST_FLAG_PROF, cols,
|
||||
col_table_test_json_order, sizeof(col_table_test_json_order) /
|
||||
sizeof(col_table_test_json_order[0]));
|
||||
COL_TABLE_TEST_NCOLS, COL_TABLE_TEST_FLAG_PROF, cols);
|
||||
emitter_json_object_end(emitter);
|
||||
emitter_table_row(emitter, &row);
|
||||
emitter_json_array_end(emitter);
|
||||
|
|
@ -761,17 +758,19 @@ static const char *col_table_json =
|
|||
"{\n"
|
||||
"\t\"rows\": [\n"
|
||||
"\t\t{\n"
|
||||
"\t\t\t\"requests\": 9,\n"
|
||||
"\t\t\t\"count\": 7,\n"
|
||||
"\t\t\t\"prof_count\": 100,\n"
|
||||
"\t\t\t\"count\": 7\n"
|
||||
"\t\t\t\"label\": \"row\",\n"
|
||||
"\t\t\t\"requests\": 9\n"
|
||||
"\t\t}\n"
|
||||
"\t]\n"
|
||||
"}\n";
|
||||
static const char *col_table_json_compact =
|
||||
"{\"rows\":[{\"requests\":9,\"prof_count\":100,\"count\":7}]}";
|
||||
"{\"rows\":[{\"count\":7,\"prof_count\":100,\"label\":\"row\","
|
||||
"\"requests\":9}]}";
|
||||
static const char *col_table_table =
|
||||
"mock:size count prof requests\n"
|
||||
" 42 7 100 9\n";
|
||||
"mock:size count prof label requests\n"
|
||||
" 42 7 100 row 9\n";
|
||||
|
||||
#define GENERATE_TEST(feature) \
|
||||
TEST_BEGIN(test_##feature) { \
|
||||
|
|
|
|||
|
|
@ -288,6 +288,70 @@ json_find_named_array(
|
|||
return array_begin;
|
||||
}
|
||||
|
||||
static void
|
||||
expect_json_keys_before(const char *begin, const char *end,
|
||||
const char *const *keys, size_t nkeys, const char *section_name) {
|
||||
for (size_t i = 0; i < nkeys; i++) {
|
||||
char search_key[128];
|
||||
size_t written = malloc_snprintf(
|
||||
search_key, sizeof(search_key), "\"%s\":", keys[i]);
|
||||
expect_zu_lt(written, sizeof(search_key), "JSON key is too long");
|
||||
const char *found = strstr(begin, search_key);
|
||||
expect_true(found != NULL && found < end,
|
||||
"%s should contain %s", section_name, keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_BEGIN(test_json_stats_table_columns) {
|
||||
test_skip_if(!config_stats);
|
||||
|
||||
uint64_t epoch = 1;
|
||||
expect_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
|
||||
0, "Unexpected mallctl() failure");
|
||||
|
||||
stats_buf_t sbuf;
|
||||
stats_buf_init(&sbuf);
|
||||
malloc_stats_print(stats_buf_write_cb, &sbuf, "Ja");
|
||||
|
||||
const char *bins_end = NULL;
|
||||
const char *bins = json_find_named_array(sbuf.buf, "bins", &bins_end);
|
||||
expect_ptr_not_null(bins, "JSON output should contain bins");
|
||||
const char *bin_keys[] = {"size", "ind", "allocated", "nmalloc_ps",
|
||||
"nshards", "regs", "pgs", "util", "nslabs"};
|
||||
expect_json_keys_before(bins, bins_end, bin_keys,
|
||||
sizeof(bin_keys) / sizeof(bin_keys[0]), "bins");
|
||||
|
||||
const char *lextents_end = NULL;
|
||||
const char *lextents = json_find_named_array(
|
||||
sbuf.buf, "lextents", &lextents_end);
|
||||
expect_ptr_not_null(lextents, "JSON output should contain lextents");
|
||||
const char *lextent_keys[] = {"size", "ind", "allocated", "nmalloc",
|
||||
"nmalloc_ps", "ndalloc", "ndalloc_ps", "nrequests",
|
||||
"nrequests_ps"};
|
||||
expect_json_keys_before(lextents, lextents_end, lextent_keys,
|
||||
sizeof(lextent_keys) / sizeof(lextent_keys[0]), "lextents");
|
||||
|
||||
const char *extents_end = NULL;
|
||||
const char *extents = json_find_named_array(
|
||||
sbuf.buf, "extents", &extents_end);
|
||||
expect_ptr_not_null(extents, "JSON output should contain extents");
|
||||
const char *extent_keys[] = {"size", "ind", "ntotal", "total_bytes"};
|
||||
expect_json_keys_before(extents, extents_end, extent_keys,
|
||||
sizeof(extent_keys) / sizeof(extent_keys[0]), "extents");
|
||||
|
||||
const char *full_slabs_end = NULL;
|
||||
const char *full_slabs = json_find_named_object(
|
||||
sbuf.buf, "full_slabs", &full_slabs_end);
|
||||
expect_ptr_not_null(
|
||||
full_slabs, "JSON output should contain full_slabs");
|
||||
const char *hpa_keys[] = {"size", "ind"};
|
||||
expect_json_keys_before(full_slabs, full_slabs_end, hpa_keys,
|
||||
sizeof(hpa_keys) / sizeof(hpa_keys[0]), "full_slabs");
|
||||
|
||||
stats_buf_fini(&sbuf);
|
||||
}
|
||||
TEST_END
|
||||
|
||||
TEST_BEGIN(test_json_stats_mutexes) {
|
||||
test_skip_if(!config_stats);
|
||||
|
||||
|
|
@ -502,7 +566,8 @@ TEST_END
|
|||
|
||||
int
|
||||
main(void) {
|
||||
return test_no_reentrancy(test_json_stats_mutexes,
|
||||
return test_no_reentrancy(test_json_stats_table_columns,
|
||||
test_json_stats_mutexes,
|
||||
test_hpa_shard_json_ndirty_huge,
|
||||
test_hpa_shard_json_contains_sec_stats,
|
||||
test_hpa_shard_json_contains_retained_stats);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue