void ia_doer_init(iadoer *doer, int nth, long benchmask, int key_space, int key_sequence) { assert(benchmask); doer->ctx = NULL; doer->nth = nth; doer->benchmask = benchmask; doer->key_space = key_space; doer->key_sequence = key_sequence; if (benchmask) { char line[1024], *s; iabenchmark bench; s = line; for(bench = IA_SET; bench < IA_MAX; ++bench) if (benchmask & (1l << bench)) s += snprintf(s, line + sizeof(line) - s, "%s%s", s != line ? ", " : "", ia_benchmarkof(bench)); ia_log("doer.%d: {%s}, key-space %d, key-sequence %d", doer->nth, line, key_space, key_sequence); } ia_kvpool_init(&doer->pool, ioarena.conf.ksize, ioarena.conf.vsize, doer->key_space, doer->key_sequence, ioarena.conf.count); ia_kvpool_fill(&doer->pool, ioarena.conf.count, 2); ia_histogram_init(&doer->hg); __sync_fetch_and_add(&ioarena.doers_count, 1); }
int ia_init(ia *a, int argc, char **argv) { int rc; ia_log("IOARENA (embedded storage benchmarking)\n"); rc = ia_configinit(&a->conf); if (rc == -1) return -1; rc = ia_configparse(&a->conf, argc, argv); if (rc == -1 || rc == 1) return rc; ia_configprint(&a->conf); a->driver = a->conf.driver_if; mkdir(ioarena.conf.path, 0755); snprintf(a->datadir, sizeof(a->datadir), "%s/%s", ioarena.conf.path, a->driver->name); mkdir(a->datadir, 0755); iarusage before_open; rc = ia_get_rusage(&before_open, a->datadir); if (rc) return -1; a->before_open_ram = before_open.ram; rc = a->driver->open(a->datadir); if (rc == -1) return -1; return 0; }
void ia_kvpool_fill(struct iakvpool *pool, size_t nbandles, size_t nelem) { size_t i, j, bytes = nbandles * nelem * (pool->vsize + pool->ksize); char* dst = realloc(pool->flat, bytes); if (! dst) { ia_log("error: out of memory"); ia_fatal(__func__); } pool->flat = dst; for (i = 0; i < nbandles; ++i) { uint64_t point = pool->space + pool->serial; pool->serial = (pool->serial + 1) % pool->period; for (j = 0; j < nelem; ++j) { dst = kv_rnd(&point, dst, !ioarena.conf.binary, pool->ksize); if (pool->vsize) dst = kv_rnd(&point, dst, !ioarena.conf.binary, pool->vsize); } } assert(dst == pool->flat + bytes); pool->pos = 0; pool->power = bytes; }
static void ia_sync_fihish(ia *a) { int rc = pthread_barrier_wait(&a->barrier_fihish); if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { ia_log("error: pthread_barrier_wait %s (%d)", strerror(rc), rc); ia_fatal(__func__); } }
static void ia_sync_start(ia *a) { #ifdef _POSIX_PRIORITY_SCHEDULING sched_yield(); #elif defined(__APPLE__) || defined(__MACH__) pthread_yield_np(); #else pthread_yield(); #endif int rc = pthread_barrier_wait(&a->barrier_start); if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { ia_log("error: pthread_barrier_wait %s (%d)", strerror(rc), rc); ia_fatal(__func__); } }
static FILE* csv_create(const iaconfig *config, const char* item) { FILE* f = NULL; if(config->csv_prefix) { char path[PATH_MAX]; snprintf(path, sizeof(path), "%s%s_%s_%s.csv", config->csv_prefix, config->driver, ia_syncmode2str(config->syncmode), item); f = fopen(path, "w"); if (! f) ia_log("error: %s, %s (%d)", path, strerror(errno), errno); } return f; }
static void ia_keynotfound(iadoer *doer, const char *op, iakv *k) { ia_log("error: key %s not found (%s, #%d, %d+%d)", k->k, op, doer->nth, doer->key_space, doer->key_sequence); }
int ia_run(ia *a) { long set_rd = 0; long set_wr = 0; iabenchmark bench; for (bench = IA_SET; bench < IA_MAX; bench++) { if (! a->conf.benchmark_list[bench]) continue; ia_histogram_enable(bench); if (bench == IA_ITERATE || bench == IA_GET) set_rd |= 1l << bench; else set_wr |= 1l << bench; } if ((set_rd | set_wr) == 0) return 0; if (a->conf.rthr && set_rd == 0) a->conf.rthr = 0; if (a->conf.wthr && set_wr == 0) a->conf.wthr = 0; int key_nsectors = 1; if (key_nsectors < a->conf.rthr) key_nsectors = a->conf.rthr; if (key_nsectors < a->conf.wthr) key_nsectors = a->conf.wthr; int key_nspaces = 1; if (key_nspaces < a->conf.wthr) key_nspaces = a->conf.wthr; if (set_wr & bench_mask_2keyspace) key_nspaces += key_nspaces; int rc = ia_kvgen_setup(!ioarena.conf.binary, ioarena.conf.ksize, key_nspaces, key_nsectors, ioarena.conf.count, ioarena.conf.kvseed); if (rc) { ia_log("error: key-value generator setup failed, the options are correct?"); return rc; } rc = pthread_barrier_init(&a->barrier_start, NULL, a->conf.rthr + a->conf.wthr + 1); if (!rc) rc = pthread_barrier_init(&a->barrier_fihish, NULL, a->conf.rthr + a->conf.wthr + 1); if (rc) { ia_log("error: pthread_barrier_init %s (%d)", strerror(errno), errno); return rc; } ia_histogram_csvopen(&a->conf); int nth = 0; int key_space = 0; rc = ia_spread(a->conf.rthr, &nth, &set_rd, set_rd, &key_space); if (rc) goto bailout; rc = ia_spread(a->conf.wthr, &nth, &set_wr, set_wr, &key_space); if (rc) goto bailout; iarusage rusage_start, rusage_fihish; if (set_wr | set_rd) { iadoer here; if (ia_doer_init(&here, 0, set_wr | set_rd, 0, 0)) goto bailout; rc = ia_get_rusage(&rusage_start, a->datadir); if (rc) goto bailout; ia_sync_start(a); rc = ia_doer_fulfil(&here); ia_sync_fihish(a); if (rc) goto bailout; rc = ia_get_rusage(&rusage_fihish, a->datadir); if (rc) goto bailout; ia_doer_destroy(&here); } else { rc = ia_get_rusage(&rusage_start, a->datadir); if (rc) goto bailout; ia_sync_start(a); ia_sync_fihish(a); rc = ia_get_rusage(&rusage_fihish, a->datadir); if (rc) goto bailout; } if (a->failed) goto bailout; ia_histogram_checkpoint(0); ia_log("complete."); ia_histogram_print(&a->conf); rusage_start.ram = a->before_open_ram; rusage_start.disk = 0; ia_histogram_rusage(&a->conf, &rusage_start, &rusage_fihish); ia_histogram_csvclose(); return 0; bailout: exit(EXIT_FAILURE); }
int ia_histogram_checkpoint(ia_timestamp_t now) { if (now) { if (now - global.checkpoint_ns < INTERVAL_STAT) return -1; if (global.doers_active > ++global.doers_merged) return 0; } if (global.doers_active != global.doers_merged) ia_fatal(__FUNCTION__); if (! now) now = ia_timestamp_ns(); iahistogram *h; char line[1024], *s; if (global.checkpoint_ns == global.starting_point) { s = line; s += snprintf(s, line + sizeof(line) - s, " time"); if (global.csv_timeline) fprintf(global.csv_timeline, "\ttime" ); for (h = global.per_bench; h < global.per_bench + IA_MAX; ++h) { if (! h->enabled) continue; const char *name = ia_benchmarkof(h->bench); s += snprintf(s, line + sizeof(line) - s, " | bench rps min avg rms max vol #N"); if (global.csv_timeline) fprintf(global.csv_timeline, ",\t%s_rps,\t%s_min,\t%s_avg,\t%s_rms,\t%s_max", name, name, name, name, name); } if (global.csv_timeline) fprintf(global.csv_timeline, "\n"); ia_log("%s", line); } s = line; const double timepoint = (now - global.starting_point) / (double) S; s += snprintf(s, line + sizeof(line) - s, "%9.3f", timepoint); if (global.csv_timeline) fprintf(global.csv_timeline, "%e", timepoint); const ia_timestamp_t wall_ns = now - global.checkpoint_ns; const double wall = wall_ns / (double) S; global.checkpoint_ns = now; for (h = global.per_bench; h < global.per_bench + IA_MAX; ++h) { if (! h->enabled) continue; const char *name = ia_benchmarkof(h->bench); const uint64_t n = h->acc.n - h->last.n; const uint64_t vol = h->acc.volume_sum - h->last.volume_sum; s += snprintf(s, line + sizeof(line) - s, " | %5s", name ); if (n) { const ia_timestamp_t rms = sqrt((h->acc.latency_sum_square - h->last.latency_sum_square) / n); const ia_timestamp_t avg = (h->acc.latency_sum_ns - h->last.latency_sum_ns) / n; const double rps = n / wall; const double bps = vol / wall; if (global.csv_timeline) { fprintf(global.csv_timeline, ",\t%e,\t%e,\t%e,\t%e,\t%e", rps, h->min / (double) S, avg / (double) S, rms / (double) S, h->max / (double) S); } s += snprintf(s, line + sizeof(line) - s, ":"); s += snpf_val(s, line + sizeof(line) - s, rps, ""); s += snpf_lat(s, line + sizeof(line) - s, h->min); s += snpf_lat(s, line + sizeof(line) - s, avg); s += snpf_lat(s, line + sizeof(line) - s, rms); s += snpf_lat(s, line + sizeof(line) - s, h->max); s += snpf_val(s, line + sizeof(line) - s, bps, "bps"); s += snpf_val(s, line + sizeof(line) - s, h->acc.n, ""); } else { s += snprintf(s, line + sizeof(line) - s, " - - - - - - - "); if (global.csv_timeline) { fprintf(global.csv_timeline, ",\t\t,\t\t,\t\t,\t\t"); } } if (h->whole_min > h->min) h->whole_min = h->min; h->min = ~0ull; if (h->whole_max < h->max) h->whole_max = h->max; h->max = 0; h->last = h->acc; } if (global.csv_timeline) { fprintf(global.csv_timeline, "\n"); fflush(global.csv_timeline); } ia_log("%s", line); assert(global.doers_active == global.doers_merged); global.doers_merged = 0; global.merge_evo += 1; return 1; }