Workbench API improved.
parent
d9c74af8f3
commit
c0ffdf44d0
|
@ -26,6 +26,50 @@ It follows the hierarchical file system semantics in contrast to the md-workbenc
|
||||||
|
|
||||||
#define oprintf(...) do { fprintf(o.logfile, __VA_ARGS__); fflush(o.logfile); } while(0);
|
#define oprintf(...) do { fprintf(o.logfile, __VA_ARGS__); fflush(o.logfile); } while(0);
|
||||||
|
|
||||||
|
// successfull, errors
|
||||||
|
typedef struct {
|
||||||
|
int suc;
|
||||||
|
int err;
|
||||||
|
} op_stat_t;
|
||||||
|
|
||||||
|
// A runtime for an operation and when the operation was started
|
||||||
|
typedef struct{
|
||||||
|
float time_since_app_start;
|
||||||
|
float runtime;
|
||||||
|
} time_result_t;
|
||||||
|
|
||||||
|
|
||||||
|
// statistics for running a single phase
|
||||||
|
typedef struct{ // NOTE: if this type is changed, adjust end_phase() !!!
|
||||||
|
double t; // maximum time
|
||||||
|
double * t_all;
|
||||||
|
|
||||||
|
op_stat_t dset_create;
|
||||||
|
op_stat_t dset_delete;
|
||||||
|
|
||||||
|
op_stat_t obj_create;
|
||||||
|
op_stat_t obj_read;
|
||||||
|
op_stat_t obj_stat;
|
||||||
|
op_stat_t obj_delete;
|
||||||
|
|
||||||
|
// time measurements of individual runs, these are not returned for now by the API!
|
||||||
|
uint64_t repeats;
|
||||||
|
time_result_t * time_create;
|
||||||
|
time_result_t * time_read;
|
||||||
|
time_result_t * time_stat;
|
||||||
|
time_result_t * time_delete;
|
||||||
|
|
||||||
|
time_statistics_t stats_create;
|
||||||
|
time_statistics_t stats_read;
|
||||||
|
time_statistics_t stats_stat;
|
||||||
|
time_statistics_t stats_delete;
|
||||||
|
|
||||||
|
// the maximum time for any single operation
|
||||||
|
double max_op_time;
|
||||||
|
double phase_start_timer;
|
||||||
|
int stonewall_iterations;
|
||||||
|
} phase_stat_t;
|
||||||
|
|
||||||
struct benchmark_options{
|
struct benchmark_options{
|
||||||
ior_aiori_t const * backend;
|
ior_aiori_t const * backend;
|
||||||
void * backend_options;
|
void * backend_options;
|
||||||
|
@ -38,7 +82,7 @@ struct benchmark_options{
|
||||||
int precreate;
|
int precreate;
|
||||||
int dset_count;
|
int dset_count;
|
||||||
|
|
||||||
int result_position; // in the global structure
|
mdworkbench_results_t * results; // the results
|
||||||
|
|
||||||
int offset;
|
int offset;
|
||||||
int iterations;
|
int iterations;
|
||||||
|
@ -211,10 +255,13 @@ static void print_p_stat(char * buff, const char * name, phase_stat_t * p, doubl
|
||||||
ioops_per_iter = 2;
|
ioops_per_iter = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double rate;
|
||||||
|
|
||||||
switch(name[0]){
|
switch(name[0]){
|
||||||
case('b'):
|
case('b'):
|
||||||
|
rate = p->obj_read.suc * ioops_per_iter / t;
|
||||||
pos += sprintf(buff + pos, "rate:%.1f iops/s objects:%d rate:%.1f obj/s tp:%.1f MiB/s op-max:%.4es",
|
pos += sprintf(buff + pos, "rate:%.1f iops/s objects:%d rate:%.1f obj/s tp:%.1f MiB/s op-max:%.4es",
|
||||||
p->obj_read.suc * ioops_per_iter / t, // write, stat, read, delete
|
rate, // write, stat, read, delete
|
||||||
p->obj_read.suc,
|
p->obj_read.suc,
|
||||||
p->obj_read.suc / t,
|
p->obj_read.suc / t,
|
||||||
tp,
|
tp,
|
||||||
|
@ -225,8 +272,9 @@ static void print_p_stat(char * buff, const char * name, phase_stat_t * p, doubl
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case('p'):
|
case('p'):
|
||||||
|
rate = (p->dset_create.suc + p->obj_create.suc) / t;
|
||||||
pos += sprintf(buff + pos, "rate:%.1f iops/s dsets: %d objects:%d rate:%.3f dset/s rate:%.1f obj/s tp:%.1f MiB/s op-max:%.4es",
|
pos += sprintf(buff + pos, "rate:%.1f iops/s dsets: %d objects:%d rate:%.3f dset/s rate:%.1f obj/s tp:%.1f MiB/s op-max:%.4es",
|
||||||
(p->dset_create.suc + p->obj_create.suc) / t,
|
rate,
|
||||||
p->dset_create.suc,
|
p->dset_create.suc,
|
||||||
p->obj_create.suc,
|
p->obj_create.suc,
|
||||||
p->dset_create.suc / t,
|
p->dset_create.suc / t,
|
||||||
|
@ -235,8 +283,9 @@ static void print_p_stat(char * buff, const char * name, phase_stat_t * p, doubl
|
||||||
p->max_op_time);
|
p->max_op_time);
|
||||||
break;
|
break;
|
||||||
case('c'):
|
case('c'):
|
||||||
|
rate = (p->obj_delete.suc + p->dset_delete.suc) / t;
|
||||||
pos += sprintf(buff + pos, "rate:%.1f iops/s objects:%d dsets: %d rate:%.1f obj/s rate:%.3f dset/s op-max:%.4es",
|
pos += sprintf(buff + pos, "rate:%.1f iops/s objects:%d dsets: %d rate:%.1f obj/s rate:%.3f dset/s op-max:%.4es",
|
||||||
(p->obj_delete.suc + p->dset_delete.suc) / t,
|
rate,
|
||||||
p->obj_delete.suc,
|
p->obj_delete.suc,
|
||||||
p->dset_delete.suc,
|
p->dset_delete.suc,
|
||||||
p->obj_delete.suc / t,
|
p->obj_delete.suc / t,
|
||||||
|
@ -248,6 +297,16 @@ static void print_p_stat(char * buff, const char * name, phase_stat_t * p, doubl
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(print_global){
|
||||||
|
mdworkbench_result_t * res = & o.results->result[o.results->count];
|
||||||
|
res->errors = errs;
|
||||||
|
o.results->errors += errs;
|
||||||
|
res->rate = rate;
|
||||||
|
res->max_op_time = p->max_op_time;
|
||||||
|
res->runtime = t;
|
||||||
|
res->iterations_done = p->repeats;
|
||||||
|
}
|
||||||
|
|
||||||
if(! o.quiet_output || errs > 0){
|
if(! o.quiet_output || errs > 0){
|
||||||
pos += sprintf(buff + pos, " (%d errs", errs);
|
pos += sprintf(buff + pos, " (%d errs", errs);
|
||||||
if(errs > 0){
|
if(errs > 0){
|
||||||
|
@ -341,7 +400,7 @@ static void compute_histogram(const char * name, time_result_t * times, time_sta
|
||||||
stats->max = times[repeats - 1].runtime;
|
stats->max = times[repeats - 1].runtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void end_phase(const char * name, phase_stat_t * p, phase_stat_t * result){
|
static void end_phase(const char * name, phase_stat_t * p){
|
||||||
int ret;
|
int ret;
|
||||||
char buff[MAX_PATHLEN];
|
char buff[MAX_PATHLEN];
|
||||||
|
|
||||||
|
@ -452,8 +511,13 @@ static void end_phase(const char * name, phase_stat_t * p, phase_stat_t * result
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the result back for the API
|
// copy the result back for the API
|
||||||
memcpy(& result[o.result_position], & g_stat, sizeof(g_stat));
|
mdworkbench_result_t * res = & o.results->result[o.results->count];
|
||||||
o.result_position++;
|
memcpy(& res->stats_create, & g_stat.stats_create, sizeof(time_statistics_t));
|
||||||
|
memcpy(& res->stats_read, & g_stat.stats_read, sizeof(time_statistics_t));
|
||||||
|
memcpy(& res->stats_stat, & g_stat.stats_stat, sizeof(time_statistics_t));
|
||||||
|
memcpy(& res->stats_delete, & g_stat.stats_delete, sizeof(time_statistics_t));
|
||||||
|
|
||||||
|
o.results->count++;
|
||||||
|
|
||||||
// allocate memory if necessary
|
// allocate memory if necessary
|
||||||
// ret = mem_preallocate(& limit_memory_P, o.limit_memory_between_phases, o.verbosity >= 3);
|
// ret = mem_preallocate(& limit_memory_P, o.limit_memory_between_phases, o.verbosity >= 3);
|
||||||
|
@ -783,7 +847,7 @@ static void store_position(int position){
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE * out_logfile){
|
mdworkbench_results_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE * out_logfile){
|
||||||
int ret;
|
int ret;
|
||||||
int printhelp = 0;
|
int printhelp = 0;
|
||||||
char * limit_memory_P = NULL;
|
char * limit_memory_P = NULL;
|
||||||
|
@ -873,7 +937,10 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
double bench_start;
|
double bench_start;
|
||||||
bench_start = GetTimeStamp();
|
bench_start = GetTimeStamp();
|
||||||
phase_stat_t phase_stats;
|
phase_stat_t phase_stats;
|
||||||
phase_stat_t* all_phases_stats = malloc(sizeof(phase_stat_t) * (2 + o.iterations));
|
size_t result_count = (2 + o.iterations) * (o.adaptive_waiting_mode ? 7 : 1);
|
||||||
|
o.results = malloc(sizeof(mdworkbench_results_t) + sizeof(mdworkbench_result_t) * result_count);
|
||||||
|
memset(o.results, 0, sizeof(mdworkbench_results_t) + sizeof(mdworkbench_result_t) * result_count);
|
||||||
|
o.results->count = 0;
|
||||||
|
|
||||||
if(o.rank == 0 && o.print_detailed_stats && ! o.quiet_output){
|
if(o.rank == 0 && o.print_detailed_stats && ! o.quiet_output){
|
||||||
print_detailed_stat_header();
|
print_detailed_stat_header();
|
||||||
|
@ -892,7 +959,7 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
phase_stats.phase_start_timer = GetTimeStamp();
|
phase_stats.phase_start_timer = GetTimeStamp();
|
||||||
run_precreate(& phase_stats, current_index);
|
run_precreate(& phase_stats, current_index);
|
||||||
phase_stats.t = GetTimeStamp() - phase_stats.phase_start_timer;
|
phase_stats.t = GetTimeStamp() - phase_stats.phase_start_timer;
|
||||||
end_phase("precreate", & phase_stats, all_phases_stats);
|
end_phase("precreate", & phase_stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.phase_benchmark){
|
if (o.phase_benchmark){
|
||||||
|
@ -905,7 +972,7 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
MPI_Barrier(o.com);
|
MPI_Barrier(o.com);
|
||||||
phase_stats.phase_start_timer = GetTimeStamp();
|
phase_stats.phase_start_timer = GetTimeStamp();
|
||||||
run_benchmark(& phase_stats, & current_index);
|
run_benchmark(& phase_stats, & current_index);
|
||||||
end_phase("benchmark", & phase_stats, all_phases_stats);
|
end_phase("benchmark", & phase_stats);
|
||||||
|
|
||||||
if(o.adaptive_waiting_mode){
|
if(o.adaptive_waiting_mode){
|
||||||
o.relative_waiting_factor = 0.0625;
|
o.relative_waiting_factor = 0.0625;
|
||||||
|
@ -914,7 +981,7 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
MPI_Barrier(o.com);
|
MPI_Barrier(o.com);
|
||||||
phase_stats.phase_start_timer = GetTimeStamp();
|
phase_stats.phase_start_timer = GetTimeStamp();
|
||||||
run_benchmark(& phase_stats, & current_index);
|
run_benchmark(& phase_stats, & current_index);
|
||||||
end_phase("benchmark", & phase_stats, all_phases_stats);
|
end_phase("benchmark", & phase_stats);
|
||||||
o.relative_waiting_factor *= 2;
|
o.relative_waiting_factor *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -927,7 +994,7 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
phase_stats.phase_start_timer = GetTimeStamp();
|
phase_stats.phase_start_timer = GetTimeStamp();
|
||||||
run_cleanup(& phase_stats, current_index);
|
run_cleanup(& phase_stats, current_index);
|
||||||
phase_stats.t = GetTimeStamp() - phase_stats.phase_start_timer;
|
phase_stats.t = GetTimeStamp() - phase_stats.phase_start_timer;
|
||||||
end_phase("cleanup", & phase_stats, all_phases_stats);
|
end_phase("cleanup", & phase_stats);
|
||||||
|
|
||||||
if (o.rank == 0){
|
if (o.rank == 0){
|
||||||
if (o.backend->rmdir(o.prefix, o.backend_options) != 0) {
|
if (o.backend->rmdir(o.prefix, o.backend_options) != 0) {
|
||||||
|
@ -947,5 +1014,5 @@ phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE
|
||||||
printTime();
|
printTime();
|
||||||
}
|
}
|
||||||
//mem_free_preallocated(& limit_memory_P);
|
//mem_free_preallocated(& limit_memory_P);
|
||||||
return all_phases_stats;
|
return o.results;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <mpi.h>
|
#include <mpi.h>
|
||||||
|
|
||||||
// successfull, errors
|
|
||||||
typedef struct {
|
|
||||||
int suc;
|
|
||||||
int err;
|
|
||||||
} op_stat_t;
|
|
||||||
|
|
||||||
// A runtime for an operation and when the operation was started
|
|
||||||
typedef struct{
|
|
||||||
float time_since_app_start;
|
|
||||||
float runtime;
|
|
||||||
} time_result_t;
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
float min;
|
float min;
|
||||||
float q1;
|
float q1;
|
||||||
|
@ -27,38 +15,28 @@ typedef struct{
|
||||||
float max;
|
float max;
|
||||||
} time_statistics_t;
|
} time_statistics_t;
|
||||||
|
|
||||||
|
|
||||||
// statistics for running a single phase
|
// statistics for running a single phase
|
||||||
typedef struct{ // NOTE: if this type is changed, adjust end_phase() !!!
|
typedef struct{ // NOTE: if this type is changed, adjust end_phase() !!!
|
||||||
double t; // maximum time
|
|
||||||
double * t_all;
|
|
||||||
|
|
||||||
op_stat_t dset_create;
|
|
||||||
op_stat_t dset_delete;
|
|
||||||
|
|
||||||
op_stat_t obj_create;
|
|
||||||
op_stat_t obj_read;
|
|
||||||
op_stat_t obj_stat;
|
|
||||||
op_stat_t obj_delete;
|
|
||||||
|
|
||||||
// time measurements of individual runs, these are not returned for now by the API!
|
|
||||||
uint64_t repeats;
|
|
||||||
time_result_t * time_create;
|
|
||||||
time_result_t * time_read;
|
|
||||||
time_result_t * time_stat;
|
|
||||||
time_result_t * time_delete;
|
|
||||||
|
|
||||||
time_statistics_t stats_create;
|
time_statistics_t stats_create;
|
||||||
time_statistics_t stats_read;
|
time_statistics_t stats_read;
|
||||||
time_statistics_t stats_stat;
|
time_statistics_t stats_stat;
|
||||||
time_statistics_t stats_delete;
|
time_statistics_t stats_delete;
|
||||||
|
|
||||||
// the maximum time for any single operation
|
int errors;
|
||||||
|
double rate;
|
||||||
double max_op_time;
|
double max_op_time;
|
||||||
double phase_start_timer;
|
double runtime;
|
||||||
int stonewall_iterations;
|
uint64_t iterations_done;
|
||||||
} phase_stat_t;
|
} mdworkbench_result_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
int count; // the number of results
|
||||||
|
int errors;
|
||||||
|
mdworkbench_result_t result[];
|
||||||
|
} mdworkbench_results_t;
|
||||||
|
|
||||||
// @Return The first statistics returned are precreate, then iteration many benchmark runs, the last is cleanup
|
// @Return The first statistics returned are precreate, then iteration many benchmark runs, the last is cleanup
|
||||||
phase_stat_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE * out_logfile);
|
mdworkbench_results_t* md_workbench_run(int argc, char ** argv, MPI_Comm world_com, FILE * out_logfile);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue