rewrite soak with more flexibility and ability to record/playback events to reproduce bugs #10
3 changed files with 373 additions and 116 deletions
2
Makefile
2
Makefile
|
@ -60,7 +60,7 @@ clean:
|
|||
rm -f $(EXAMPLES) examples/*.o
|
||||
|
||||
format:
|
||||
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/soak.c tests/test.c lib/common.c include/common.h
|
||||
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/soak.c tests/test.c tests/midl.c lib/common.c include/common.h
|
||||
# clang-format -i include/*.h src/*.c tests/*.c tests/*.h examples/*.c
|
||||
|
||||
%.o: src/%.c
|
||||
|
|
23
lib/common.c
23
lib/common.c
|
@ -51,6 +51,29 @@ tsc(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// get microsecond timestamp
|
||||
uint64_t
|
||||
msts()
|
||||
{
|
||||
#ifdef _SC_MONOTONIC_CLOCK
|
||||
struct timespec ts;
|
||||
if (sysconf(_SC_MONOTONIC_CLOCK) > 0) {
|
||||
/* A monotonic clock presents */
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||
return (uint64_t)(ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == 0)
|
||||
return (uint64_t)(tv.tv_sec * 1000000 + tv.tv_usec);
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
double
|
||||
nsts(void)
|
||||
{
|
||||
|
|
462
tests/soak.c
462
tests/soak.c
|
@ -5,6 +5,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../include/common.h"
|
||||
|
@ -14,10 +15,123 @@
|
|||
|
||||
#include "midl.c"
|
||||
|
||||
#define INITIAL_AMOUNT 1024 * 2
|
||||
|
||||
bool recording = true;
|
||||
|
||||
typedef size_t pgno_t;
|
||||
|
||||
#define INITIAL_AMOUNT 1024 * 2
|
||||
bool recording = true;
|
||||
typedef enum { SM, ML, RB } container_impl_t;
|
||||
|
||||
typedef struct container {
|
||||
const char *name;
|
||||
/* allocate a new container */
|
||||
void *(*alloc)(size_t capacity);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
void *(*alloc)(size_t capacity);
|
||||
} alloc_stats;
|
||||
|
||||
/* free the container */
|
||||
void (*free)(void *handle);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
void (*free)(void *handle);
|
||||
} free_stats;
|
||||
|
||||
/* add pg to the container */
|
||||
pgno_t (*set)(void **handle, pgno_t pg);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
pgno_t (*set)(void **handle, pgno_t pg);
|
||||
} set_stats;
|
||||
#define timed_set(fn) (pgno_t(*)(void **, pgno_t)) __stats_set, .set_stats.set = fn
|
||||
|
||||
/* is pg in the container */
|
||||
bool (*is_set)(void *handle, pgno_t pg);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*is_set)(void *handle, pgno_t pg);
|
||||
} is_set_stats;
|
||||
#define timed_is_set(fn) (bool (*)(void *, pgno_t)) __stats_is_set, .is_set_stats.is_set = fn
|
||||
|
||||
/* remove pg from the container */
|
||||
pgno_t (*clear)(void **handle, pgno_t pg);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
pgno_t (*clear)(void **handle, pgno_t pg);
|
||||
} clear_stats;
|
||||
#define timed_clear(fn) (pgno_t(*)(void **, pgno_t)) __stats_clear, .clear_stats.clear = fn
|
||||
|
||||
/* find a set of contigious page of len and return the smallest pgno */
|
||||
pgno_t (*find_span)(void *handle, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
pgno_t (*find_span)(void *handle, unsigned len);
|
||||
} find_span_stats;
|
||||
#define timed_find_span(fn) (pgno_t(*)(void *, unsigned)) __stats_find_span, .find_span_stats.find_span = fn
|
||||
|
||||
/* remove the span [pg, pg + len) from the container */
|
||||
bool (*take_span)(void **handle, pgno_t pg, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*take_span)(void **handle, pgno_t pg, unsigned len);
|
||||
} take_span_stats;
|
||||
#define timed_take_span(fn) (bool (*)(void **, pgno_t, unsigned)) __stats_take_span, .take_span_stats.take_span = fn
|
||||
|
||||
/* add the span [pg, pg + len) into the container */
|
||||
bool (*release_span)(void **handle, pgno_t pg, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*release_span)(void **handle, pgno_t pg, unsigned len);
|
||||
} release_span_stats;
|
||||
#define timed_release_span(fn) (bool (*)(void **, pgno_t, unsigned)) __stats_release_span, .release_span_stats.release_span = fn
|
||||
|
||||
/* are the pgno in the span [pg, pg+ len) in the container? */
|
||||
bool (*is_span)(void *handle, pgno_t pg, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*is_span)(void *handle, pgno_t pg, unsigned len);
|
||||
} is_span_stats;
|
||||
#define timed_is_span(fn) (bool (*)(void *, pgno_t, unsigned)) __stats_is_span, .is_span_stats.is_span = fn
|
||||
|
||||
/* are the pgno in the span [pg, pg+ len) notn in the container? */
|
||||
bool (*is_empty)(void *handle, pgno_t pg, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*is_empty)(void *handle, pgno_t pg, unsigned len);
|
||||
} is_empty_stats;
|
||||
#define timed_is_empty(fn) (bool (*)(void *, pgno_t, unsigned)) __stats_is_empty, .is_empty_stats.is_empty = fn
|
||||
|
||||
/* is the span the first one (brute force check) */
|
||||
bool (*is_first)(void *handle, pgno_t pg, unsigned len);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*is_first)(void *handle, pgno_t pg, unsigned len);
|
||||
} is_first_stats;
|
||||
#define timed_is_first(fn) (bool (*)(void *, pgno_t, unsigned)) __stats_is_first, .is_first_stats.is_first = fn
|
||||
|
||||
/* ensure that all pgno contained in other_handle are also in handle */
|
||||
bool (*merge)(void **handle, void *other_handle);
|
||||
struct {
|
||||
td_histogram_t *td;
|
||||
bool (*merge)(void **handle, void *other_handle);
|
||||
} merge_stats;
|
||||
#define timed_merge(fn) (bool (*)(void **, void *)) __stats_merge, .merge_stats.merge = fn
|
||||
|
||||
/* the bytes size of the container */
|
||||
size_t (*size)(void *handle);
|
||||
td_histogram_t *size_stats;
|
||||
|
||||
/* the number of items in the container */
|
||||
size_t (*count)(void *handle);
|
||||
td_histogram_t *count_stats;
|
||||
|
||||
/* perform internal validation on the container (optional) */
|
||||
bool (*validate)(void *handle);
|
||||
td_histogram_t *validate_stats;
|
||||
|
||||
} container_t;
|
||||
|
||||
char *
|
||||
bytes_as(double bytes, char *s, size_t size)
|
||||
|
@ -200,6 +314,8 @@ b64_decode(const char *in, unsigned char *out, size_t outlen)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* recording ------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
record_set_mutation(FILE *out, pgno_t pg)
|
||||
{
|
||||
|
@ -462,7 +578,7 @@ __midl_set(void **handle, pgno_t pg)
|
|||
}
|
||||
mdb_midl_xappend(list, pg);
|
||||
mdb_midl_sort(list);
|
||||
//assert(mdb_midl_insert(list, pg) == 0);
|
||||
// assert(mdb_midl_insert(list, pg) == 0);
|
||||
assert(__midl_validate(*handle));
|
||||
return pg;
|
||||
}
|
||||
|
@ -755,59 +871,192 @@ __roar_validate(void *handle)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* histogram ------------------------------------------------------------- */
|
||||
|
||||
typedef struct sw {
|
||||
struct timespec t1; /* start time */
|
||||
struct timespec t2; /* stop time */
|
||||
} sw_t;
|
||||
|
||||
void
|
||||
ts(struct timespec *ts)
|
||||
{
|
||||
if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
|
||||
perror("clock_gettime");
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
elapsed(struct timespec *s, struct timespec *e)
|
||||
{
|
||||
long sec, nanos;
|
||||
|
||||
sec = e->tv_sec - s->tv_sec;
|
||||
nanos = e->tv_nsec - e->tv_nsec;
|
||||
if (nanos < 0) {
|
||||
nanos += 1e9;
|
||||
sec--;
|
||||
}
|
||||
return ((double)nanos / 1e9 + (double)sec);
|
||||
}
|
||||
|
||||
static pgno_t
|
||||
__stats_set(td_histogram_t *stats, void *fn, void **handle, pgno_t pg)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
pgno_t retval = ((pgno_t(*)(void **, pgno_t))fn)(handle, pg);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((pgno_t(*)(void **, pgno_t))fn)(handle, pg);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_is_set(td_histogram_t *stats, void *fn, void *handle, pgno_t pg)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t))fn)(handle, pg);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t))fn)(handle, pg);
|
||||
}
|
||||
|
||||
static pgno_t
|
||||
__stats_clear(td_histogram_t *stats, void *fn, void **handle, pgno_t pg)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
pgno_t retval = ((pgno_t(*)(void **, pgno_t))fn)(handle, pg);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((pgno_t(*)(void **, pgno_t))fn)(handle, pg);
|
||||
}
|
||||
|
||||
static pgno_t
|
||||
__stats_find_span(td_histogram_t *stats, void *fn, void *handle, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
pgno_t retval = ((pgno_t(*)(void *, unsigned))fn)(handle, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((pgno_t(*)(void *, unsigned))fn)(handle, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_take_span(td_histogram_t *stats, void *fn, void **handle, pgno_t pg, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_release_span(td_histogram_t *stats, void *fn, void **handle, pgno_t pg, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_is_span(td_histogram_t *stats, void *fn, void *handle, pgno_t pg, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_is_empty(td_histogram_t *stats, void *fn, void *handle, pgno_t pg, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_is_first(td_histogram_t *stats, void *fn, void *handle, pgno_t pg, unsigned len)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void *, pgno_t, unsigned))fn)(handle, pg, len);
|
||||
}
|
||||
|
||||
static bool
|
||||
__stats_merge(td_histogram_t *stats, void *fn, void **handle, void *other_handle)
|
||||
{
|
||||
if (stats) {
|
||||
struct timespec s, e;
|
||||
ts(&s);
|
||||
bool retval = ((bool (*)(void **, void *))fn)(handle, other_handle);
|
||||
ts(&e);
|
||||
td_add(stats, elapsed(&s, &e), 1);
|
||||
return retval;
|
||||
}
|
||||
return ((bool (*)(void **, void *))fn)(handle, other_handle);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
typedef enum { SM, ML, RB } container_impl_t;
|
||||
|
||||
typedef struct container {
|
||||
const char *name;
|
||||
/* allocate a new container */
|
||||
void *(*alloc)(size_t capacity);
|
||||
/* free the container */
|
||||
void (*free)(void *handle);
|
||||
/* add pg to the container */
|
||||
pgno_t (*set)(void **handle, pgno_t pg);
|
||||
/* is pg in the container */
|
||||
bool (*is_set)(void *handle, pgno_t pg);
|
||||
/* remove pg from the container */
|
||||
pgno_t (*clear)(void **handle, pgno_t pg);
|
||||
/* find a set of contigious page of len and return the smallest pgno */
|
||||
pgno_t (*find_span)(void *handle, unsigned len);
|
||||
/* remove the span [pg, pg + len) from the container */
|
||||
bool (*take_span)(void **handle, pgno_t pg, unsigned len);
|
||||
/* add the span [pg, pg + len) into the container */
|
||||
bool (*release_span)(void **handle, pgno_t pg, unsigned len);
|
||||
/* are the pgno in the span [pg, pg+ len) in the container? */
|
||||
bool (*is_span)(void *handle, pgno_t pg, unsigned len);
|
||||
/* are the pgno in the span [pg, pg+ len) notn in the container? */
|
||||
bool (*is_empty)(void *handle, pgno_t pg, unsigned len);
|
||||
/* is the span the first one (brute force check) */
|
||||
bool (*is_first)(void *handle, pgno_t pg, unsigned len);
|
||||
/* ensure that all pgno contained in other_handle are also in handle */
|
||||
bool (*merge)(void **handle, void *other_handle);
|
||||
/* the bytes size of the container */
|
||||
size_t (*size)(void *handle);
|
||||
/* the number of items in the container */
|
||||
size_t (*count)(void *handle);
|
||||
/* perform internal validation on the container (optional) */
|
||||
bool (*validate)(void *handle);
|
||||
} container_t;
|
||||
|
||||
// clang-format off
|
||||
container_t containers[] = {
|
||||
{ "sparsemap",
|
||||
.alloc = __sm_alloc,
|
||||
.free = __sm_free,
|
||||
.set = __sm_set,
|
||||
.is_set = __sm_is_set,
|
||||
.clear = __sm_clear,
|
||||
.find_span = __sm_find_span,
|
||||
.take_span = __sm_take_span,
|
||||
.release_span = __sm_release_span,
|
||||
.is_span = __sm_is_span,
|
||||
.is_empty = __sm_is_empty,
|
||||
.is_first = __sm_is_first,
|
||||
.merge = __sm_merge,
|
||||
.set = timed_set(__sm_set),
|
||||
.is_set = timed_is_set(__sm_is_set),
|
||||
.clear = timed_clear(__sm_clear),
|
||||
.find_span = timed_find_span(__sm_find_span),
|
||||
.take_span = timed_take_span(__sm_take_span),
|
||||
.release_span = timed_release_span(__sm_release_span),
|
||||
.is_span = timed_is_span(__sm_is_span),
|
||||
.is_empty = timed_is_empty(__sm_is_empty),
|
||||
.is_first = timed_is_first(__sm_is_first),
|
||||
.merge = timed_merge(__sm_merge),
|
||||
.size = __sm_size,
|
||||
.count = __sm_count,
|
||||
.validate = NULL
|
||||
|
@ -815,16 +1064,16 @@ container_t containers[] = {
|
|||
{ "midl",
|
||||
.alloc = __midl_alloc,
|
||||
.free = __midl_free,
|
||||
.set = __midl_set,
|
||||
.is_set = __midl_is_set,
|
||||
.clear = __midl_clear,
|
||||
.find_span = __midl_find_span,
|
||||
.take_span = __midl_take_span,
|
||||
.release_span = __midl_release_span,
|
||||
.is_span = __midl_is_span,
|
||||
.is_empty = __midl_is_empty,
|
||||
.is_first = NULL,
|
||||
.merge = __midl_merge,
|
||||
.set = timed_set(__midl_set),
|
||||
.is_set = timed_is_set(__midl_is_set),
|
||||
.clear = timed_clear(__midl_clear),
|
||||
.find_span = timed_find_span(__midl_find_span),
|
||||
.take_span = timed_take_span(__midl_take_span),
|
||||
.release_span = timed_release_span(__midl_release_span),
|
||||
.is_span = timed_is_span(__midl_is_span),
|
||||
.is_empty = timed_is_empty(__midl_is_empty),
|
||||
.is_first = timed_is_first(NULL),
|
||||
.merge = timed_merge(__midl_merge),
|
||||
.size = __midl_size,
|
||||
.count = __midl_count,
|
||||
.validate = __midl_validate
|
||||
|
@ -832,16 +1081,16 @@ container_t containers[] = {
|
|||
{ "roaring",
|
||||
.alloc = __roar_alloc,
|
||||
.free = __roar_free,
|
||||
.set = __roar_set,
|
||||
.is_set = __roar_is_set,
|
||||
.clear = __roar_clear,
|
||||
.find_span = __roar_find_span,
|
||||
.take_span = __roar_take_span,
|
||||
.release_span = __roar_release_span,
|
||||
.is_span = __roar_is_span,
|
||||
.is_empty = __roar_is_empty,
|
||||
.is_first = NULL,
|
||||
.merge = __roar_merge,
|
||||
.set = timed_set(__roar_set),
|
||||
.is_set = timed_is_set(__roar_is_set),
|
||||
.clear = timed_clear(__roar_clear),
|
||||
.find_span = timed_find_span(__roar_find_span),
|
||||
.take_span = timed_take_span(__roar_take_span),
|
||||
.release_span = timed_release_span(__roar_release_span),
|
||||
.is_span = timed_is_span(__roar_is_span),
|
||||
.is_empty = timed_is_empty(__roar_is_empty),
|
||||
.is_first = timed_is_first(NULL),
|
||||
.merge = timed_merge(__roar_merge),
|
||||
.size = __roar_size,
|
||||
.count = __roar_count,
|
||||
.validate = __roar_validate,
|
||||
|
@ -849,6 +1098,8 @@ container_t containers[] = {
|
|||
};
|
||||
// clang-format on
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void *handles[(sizeof((containers)) / sizeof((containers)[0]))];
|
||||
void *new_handles[(sizeof((containers)) / sizeof((containers)[0]))];
|
||||
FILE *fp;
|
||||
|
@ -857,8 +1108,11 @@ FILE *fp;
|
|||
#define cast(type, fn, ...) \
|
||||
if (containers[type].fn) \
|
||||
containers[type].fn(handles[type], ##__VA_ARGS__)
|
||||
#define invoke(type, fn, ...) containers[type].fn(handles[type], __VA_ARGS__)
|
||||
#define mutate(type, fn, ...) (type == 0) ? record_##fn##_mutation(fp, __VA_ARGS__) : (void)0, containers[type].fn(&handles[type], __VA_ARGS__)
|
||||
|
||||
#define invoke(type, fn, ...) __stats_##fn(containers[type].fn##_stats.td, containers[type].fn##_stats.fn, handles[type], __VA_ARGS__)
|
||||
#define mutate(type, fn, ...) \
|
||||
(type == 0) ? record_##fn##_mutation(fp, __VA_ARGS__) : (void)0, \
|
||||
__stats_##fn(containers[type].fn##_stats.td, containers[type].fn##_stats.fn, &handles[type], __VA_ARGS__)
|
||||
#define foreach(set) for (unsigned type = 0; type < (sizeof((set)) / sizeof((set)[0])); type++)
|
||||
#define checkpoint(set) \
|
||||
for (unsigned type = 1; type < (sizeof((set)) / sizeof((set)[0])); type++) { \
|
||||
|
@ -932,45 +1186,6 @@ verify_eq(unsigned a, void *ad, unsigned b, void *bd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
td_histogram_t *l_span_loc;
|
||||
td_histogram_t *b_span_loc;
|
||||
td_histogram_t *l_span_take;
|
||||
td_histogram_t *b_span_take;
|
||||
td_histogram_t *l_span_merge;
|
||||
td_histogram_t *b_span_merge;
|
||||
|
||||
void
|
||||
stats_header(void)
|
||||
{
|
||||
printf(
|
||||
"timestamp,iterations,idl_cap,idl_used,idl_bytes,sm_cap,sm_used,idl_loc_p50,idl_loc_p75,idl_loc_p90,idl_loc_p99,idl_loc_p999,sm_loc_p50,sm_loc_p75,sm_loc_p90,sm_loc_p99,sm_loc_p999,idl_take_p50,idl_take_p75,idl_take_p90,idl_take_p99,idl_take_p999,sm_take_p50,sm_take_p75,sm_take_p90,sm_take_p99,sm_take_p999,idl_merge_p50,idl_merge_p75,idl_merge_p90,idl_merge_p99,idl_merge_p999,sm_merge_p50,sm_merge_p75,sm_merge_p90,sm_merge_p99,sm_merge_p999\n");
|
||||
}
|
||||
|
||||
void
|
||||
stats(size_t iterations, sparsemap_t *map, MDB_IDL list)
|
||||
{
|
||||
if (iterations < 10)
|
||||
return;
|
||||
|
||||
td_compress(l_span_loc);
|
||||
td_compress(b_span_loc);
|
||||
td_compress(l_span_take);
|
||||
td_compress(b_span_take);
|
||||
td_compress(l_span_merge);
|
||||
td_compress(b_span_merge);
|
||||
|
||||
printf(
|
||||
"%f,%zu,%zu,%zu,%zu,%zu,%zu,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f\n",
|
||||
nsts(), iterations, list[-1], list[0], MDB_IDL_SIZEOF(list), sparsemap_get_capacity(map), sparsemap_get_size(map), td_quantile(l_span_loc, .5),
|
||||
td_quantile(l_span_loc, .75), td_quantile(l_span_loc, .90), td_quantile(l_span_loc, .99), td_quantile(l_span_loc, .999), td_quantile(b_span_loc, .5),
|
||||
td_quantile(b_span_loc, .75), td_quantile(b_span_loc, .90), td_quantile(b_span_loc, .99), td_quantile(b_span_loc, .999), td_quantile(l_span_take, .5),
|
||||
td_quantile(l_span_take, .75), td_quantile(l_span_take, .90), td_quantile(l_span_take, .99), td_quantile(l_span_take, .999), td_quantile(b_span_take, .5),
|
||||
td_quantile(b_span_take, .75), td_quantile(b_span_take, .90), td_quantile(b_span_take, .99), td_quantile(b_span_take, .999), td_quantile(l_span_merge, .5),
|
||||
td_quantile(l_span_merge, .75), td_quantile(l_span_merge, .90), td_quantile(l_span_merge, .99), td_quantile(l_span_merge, .999),
|
||||
td_quantile(b_span_merge, .5), td_quantile(b_span_merge, .75), td_quantile(b_span_merge, .90), td_quantile(b_span_merge, .99),
|
||||
td_quantile(b_span_merge, .999));
|
||||
}
|
||||
|
||||
#define SHORT_OPT "r:fa:bh"
|
||||
#define LONG_OPT "record:,force,amount:,buffer,help"
|
||||
|
||||
|
@ -1051,6 +1266,25 @@ main(int argc, char *argv[])
|
|||
unsigned types[] = { SM, ML, RB };
|
||||
unsigned num_types = (sizeof((types)) / sizeof((types)[0]));
|
||||
|
||||
foreach(types)
|
||||
{
|
||||
containers[type].alloc_stats.td = NULL;
|
||||
containers[type].free_stats.td = NULL;
|
||||
containers[type].set_stats.td = td_new(100);
|
||||
containers[type].is_set_stats.td = td_new(100);
|
||||
containers[type].clear_stats.td = td_new(100);
|
||||
containers[type].find_span_stats.td = td_new(100);
|
||||
containers[type].take_span_stats.td = td_new(100);
|
||||
containers[type].release_span_stats.td = td_new(100);
|
||||
containers[type].is_span_stats.td = NULL;
|
||||
containers[type].is_empty_stats.td = NULL;
|
||||
containers[type].is_first_stats.td = NULL;
|
||||
containers[type].merge_stats.td = td_new(100);
|
||||
containers[type].size = NULL;
|
||||
containers[type].count = NULL;
|
||||
containers[type].validate = NULL;
|
||||
}
|
||||
|
||||
/* Setup: add an amt of bits to each container. */
|
||||
foreach(types)
|
||||
{
|
||||
|
@ -1142,10 +1376,10 @@ main(int argc, char *argv[])
|
|||
for (size_t i = 0; i < new_amt; i++) {
|
||||
// We don't want to record and we're using new_handles not
|
||||
// handles, so call fn directly.
|
||||
assert(containers[type].is_set(handles[type], i + new_offset) == false);
|
||||
assert(containers[type].is_set(new_handles[type], i + new_offset) == false);
|
||||
containers[type].set(&new_handles[type], i + new_offset);
|
||||
assert(containers[type].is_set(new_handles[type], i + new_offset) == true);
|
||||
assert(containers[type].is_set_stats.is_set(handles[type], i + new_offset) == false);
|
||||
assert(containers[type].is_set_stats.is_set(new_handles[type], i + new_offset) == false);
|
||||
containers[type].set_stats.set(&new_handles[type], i + new_offset);
|
||||
assert(containers[type].is_set_stats.is_set(new_handles[type], i + new_offset) == true);
|
||||
}
|
||||
}
|
||||
foreach(types)
|
||||
|
|
Loading…
Reference in a new issue