Implement opt.stats_interval and the _opts options.

Add options stats_interval and stats_interval_opts to allow interval based stats
printing.  This provides an easy way to collect stats without code changes,
because opt.stats_print may not work (some binaries never exit).
This commit is contained in:
Qi Wang
2020-01-13 22:29:17 -08:00
committed by Qi Wang
parent d71a145ec1
commit 88b0e03a4e
14 changed files with 334 additions and 50 deletions

128
test/unit/counter.c Normal file
View File

@@ -0,0 +1,128 @@
#include "test/jemalloc_test.h"
static const uint64_t interval = 1 << 20;
TEST_BEGIN(test_counter_accum) {
uint64_t increment = interval >> 4;
unsigned n = interval / increment;
uint64_t accum = 0;
counter_accum_t c;
counter_accum_init(&c, interval);
tsd_t *tsd = tsd_fetch();
bool trigger;
for (unsigned i = 0; i < n; i++) {
trigger = counter_accum(tsd_tsdn(tsd), &c, increment);
accum += increment;
if (accum < interval) {
assert_b_eq(trigger, false, "Should not trigger");
} else {
assert_b_eq(trigger, true, "Should have triggered");
}
}
assert_b_eq(trigger, true, "Should have triggered");
}
TEST_END
void
assert_counter_value(counter_accum_t *c, uint64_t v) {
uint64_t accum;
#ifdef JEMALLOC_ATOMIC_U64
accum = atomic_load_u64(&(c->accumbytes), ATOMIC_RELAXED);
#else
accum = c->accumbytes;
#endif
assert_u64_eq(accum, v, "Counter value mismatch");
}
TEST_BEGIN(test_counter_rollback) {
uint64_t half_interval = interval / 2;
counter_accum_t c;
counter_accum_init(&c, interval);
tsd_t *tsd = tsd_fetch();
counter_rollback(tsd_tsdn(tsd), &c, half_interval);
bool trigger;
trigger = counter_accum(tsd_tsdn(tsd), &c, half_interval);
assert_b_eq(trigger, false, "Should not trigger");
counter_rollback(tsd_tsdn(tsd), &c, half_interval + 1);
assert_counter_value(&c, 0);
trigger = counter_accum(tsd_tsdn(tsd), &c, half_interval);
assert_b_eq(trigger, false, "Should not trigger");
counter_rollback(tsd_tsdn(tsd), &c, half_interval - 1);
assert_counter_value(&c, 1);
counter_rollback(tsd_tsdn(tsd), &c, 1);
assert_counter_value(&c, 0);
trigger = counter_accum(tsd_tsdn(tsd), &c, half_interval);
assert_b_eq(trigger, false, "Should not trigger");
counter_rollback(tsd_tsdn(tsd), &c, 1);
assert_counter_value(&c, half_interval - 1);
trigger = counter_accum(tsd_tsdn(tsd), &c, half_interval);
assert_b_eq(trigger, false, "Should not trigger");
assert_counter_value(&c, interval - 1);
trigger = counter_accum(tsd_tsdn(tsd), &c, 1);
assert_b_eq(trigger, true, "Should have triggered");
assert_counter_value(&c, 0);
trigger = counter_accum(tsd_tsdn(tsd), &c, interval + 1);
assert_b_eq(trigger, true, "Should have triggered");
assert_counter_value(&c, 1);
}
TEST_END
#define N_THDS (16)
#define N_ITER_THD (1 << 12)
#define ITER_INCREMENT (interval >> 4)
static void *
thd_start(void *varg) {
counter_accum_t *c = (counter_accum_t *)varg;
tsd_t *tsd = tsd_fetch();
bool trigger;
uintptr_t n_triggered = 0;
for (unsigned i = 0; i < N_ITER_THD; i++) {
trigger = counter_accum(tsd_tsdn(tsd), c, ITER_INCREMENT);
n_triggered += trigger ? 1 : 0;
}
return (void *)n_triggered;
}
TEST_BEGIN(test_counter_mt) {
counter_accum_t shared_c;
counter_accum_init(&shared_c, interval);
thd_t thds[N_THDS];
unsigned i;
for (i = 0; i < N_THDS; i++) {
thd_create(&thds[i], thd_start, (void *)&shared_c);
}
uint64_t sum = 0;
for (i = 0; i < N_THDS; i++) {
void *ret;
thd_join(thds[i], &ret);
sum += (uintptr_t)ret;
}
assert_u64_eq(sum, N_THDS * N_ITER_THD / (interval / ITER_INCREMENT),
"Incorrect number of triggers");
}
TEST_END
int
main(void) {
return test(
test_counter_accum,
test_counter_rollback,
test_counter_mt);
}

View File

@@ -170,6 +170,9 @@ TEST_BEGIN(test_mallctl_opt) {
TEST_MALLCTL_OPT(ssize_t, dirty_decay_ms, always);
TEST_MALLCTL_OPT(ssize_t, muzzy_decay_ms, always);
TEST_MALLCTL_OPT(bool, stats_print, always);
TEST_MALLCTL_OPT(const char *, stats_print_opts, always);
TEST_MALLCTL_OPT(int64_t, stats_interval, always);
TEST_MALLCTL_OPT(const char *, stats_interval_opts, always);
TEST_MALLCTL_OPT(const char *, junk, fill);
TEST_MALLCTL_OPT(bool, zero, fill);
TEST_MALLCTL_OPT(bool, utrace, utrace);