#include #include #include #include #include #include #include #include #include #include #include #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include "benchmark.h" #include "config.h" #include "../thirdparty/gzstream.h" #include "ribplot.h" #ifdef ENABLE_PAPI #include #endif using namespace std; // dummy functions so that cpucache_tc can link to this extern "C" { void tc_filter_prepare() {}; tsc_t tc_filter_bench() { return 0; }; } static inline string gz_table (const string & table_name, const bool gzip) { return (gzip ? "gzfile(\"" : "\"") + table_name + (gzip ? ".gz\")" : "\""); } RibPlot::RibPlot(Benchmark * _bench, Benchmark * _thrash) : nocolor(false), gzip_tables(true), postscript(false), bench(_bench), thrash(_thrash) { } void RibPlot::invoke_R(const std::string & scriptname) { cout << "invoking R" << endl; pid_t rpid = fork(); switch (rpid) { case -1: perror("fork"); break; case 0: close(0); open(scriptname.c_str(), O_RDONLY, 0); close(1); open("/dev/null", O_RDWR, 0); execlp("R", "R", "--no-save", (char *) NULL); perror("execlp"); exit(-1); break; default: int status; waitpid(rpid, &status, 0); break; //end switch } cout << "invoking R finished" << endl; } void RibPlot::copyScript (const std::string & scriptname) { string path = RIB_DIR; ifstream plotscript ((path + "/plotscripts/" + scriptname).c_str()); string r; while (getline(plotscript, r)) { r_script << r << endl; } plotscript.close(); } void RibPlot::create_alltable() { cout << "Creating full table..." << endl; ofstream table; ofstream alltable("table.all"); bench->params.printNames(alltable, "\t"); //thrash->print_param_names(alltable, "\t"); alltable << "run\tsample\t"; bench->print_result_cols_header(alltable, ""); alltable << "\t"; thrash->print_result_cols_header(alltable, "T_"); alltable << endl; bench->params.setCurrentOrder(-1); thrash->params.setCurrentOrder(-1); int j = 0; while (bench->advance_params(-1)) { bench->params.resetAll(); while (thrash->advance_params(-1)) { thrash->params.resetAll(); std::string result_name("results/"); result_name += bench->result_filename() + "-" + thrash->result_filename(); cout << result_name; ifstream result(result_name.c_str()); string r; if (!getline(result, r)) { cerr << "error reading first line from result " << result_name << endl; exit(EXIT_FAILURE); } while (getline(result, r)) { // cout << "."; bench->params.printValues(alltable, "\t"); alltable << "\t"; // thrash->print_param_values(alltable, "\t"); alltable << r << endl; } // SPECIAL ONE TIME STUFF // int run = 0, sample = 0, action = 0, block = 0; // int oldrun = 0, oldsample = 0, oldaction = 0; // // tsc_t value = 0, valuesum = 0; // while (getline(result, r)) { // //// cout << "."; // // istringstream i(r); // // i >> run; // i >> sample; // i >> action; // i >> block; // i >> value; // // // changed run/sample/action - print sum // if (run != oldrun || sample != oldsample || action != oldaction) { // if (oldrun != 0) { // bench->print_param_values(alltable, "\t"); // alltable << "\t" << oldrun << "\t" << oldsample << "\t" << oldaction << "\t0\t" << valuesum << endl; // } // valuesum = value; // } else { // valuesum += value; // } // oldrun = run; oldsample = sample; oldaction = action; ///* // bench->print_param_values(alltable, "\t"); // // alltable << "\t"; // //// thrash->print_param_values(alltable, "\t"); // // alltable << r << endl; //*/ // } // bench->print_param_values(alltable, "\t"); // alltable << "\t" << run << "\t" << sample << "\t" << action << "\t0\t" << valuesum << endl; // cout << endl; result.close(); cout << j++ << endl; } } alltable.close(); cout << "Full table created" << endl; } void RibPlot::mult_div(const mult_div_action action, const string & colname, const string & user_param, const int bd, const int td) { // which of bench/thrash to look for divisor/multiplier parameter Benchmark * dm_bench; // prefix of div/mult_par_name string dm_prefix; const string ts = "T_"; // distinguish between column of benchmark/thrasher if (colname.compare(0, ts.length(), ts) == 0) { dm_bench = thrash.get(); dm_prefix = ts; } else { dm_bench = bench.get(); dm_prefix = ""; } vector params; if (user_param != "") { if (dm_bench->params.getOrder(user_param) == -1) { cerr << "specified divide or multiply param not applicable: " << user_param << endl; } params.push_back(user_param); } else { if (action == ACTION_DIV) { params = dm_bench->params.divParams; } else if (action == ACTION_MULT) { params = dm_bench->params.multParams; } else { assert(false); } } string oper; if (action == ACTION_DIV) { oper = " / "; } else if (action == ACTION_MULT) { oper = " * "; } else { assert(false); } for (vector::iterator par_it = params.begin(); par_it != params.end(); par_it++) { int par = dm_bench->params.getOrder(*par_it); if (par != -1) { if ((dm_bench == bench.get() && bd == par) || (dm_bench == thrash.get() && td == par)) { string par_name = dm_prefix + dm_bench->params.getName(par); r_script << "tbl[tbl$" << par_name << " > 0, ][[\"" << colname << "\"]] <- tbl[tbl$" << par_name << " > 0, ][[\"" << colname << "\"]]"; // we are just plotting the div_par on x, divide/multiply by its column r_script << oper << "tbl[tbl$" << par_name << " > 0, ][[\"" << par_name << "\"]]"; } else { r_script << "tbl[[\"" << colname << "\"]] <- tbl[[\"" << colname << "\"]]" << oper; // divide by div_par value which is constant for the whole table dm_bench->params.printCurrentValue(r_script, par, false); } r_script << endl; } } } void RibPlot::create_tables(const int filter) { cout << "Creating tables..." << endl; if (mkdir("tables", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { if (errno == EEXIST) { cout << "Directory tables already exist, rmdir to force recreation" << endl; return; } else { cout << "Error mkdir tables:" << strerror(errno) << endl; exit(EXIT_FAILURE); } } // I bet this could be done better, but.. // There is no common parent class with open() and close() methods. ogzstream * gztable = new ogzstream(); ofstream * ftable = new ofstream(); ostream * table = NULL; int bpc = bench->params.count(); int tpc = thrash->params.count(); for (int i = 0; i < bpc + tpc; i++) { int bd = (iparams.setCurrentOrder(-1); thrash->params.setCurrentOrder(-1); bench->params.resetAll(); thrash->params.resetAll(); cout << "param_depth:" << i << endl; if (!(iparams.advanceOneCheck(i):thrash->params.advanceOneCheck(i-bpc))) { continue; } do { do { bench->params.resetAll(); thrash->params.resetAll(); std::string table_name("tables/"); if (iparams.getName(bd) + "-"; } else { table_name += "T_" + thrash->params.getName(td) + "-"; } table_name += bench->table_filename(bd) + "-" + thrash->table_filename(td); // cout << "--" << table_name << endl; int j = 0; if(iparams.resetOne(i); } else { thrash->params.resetOne(i-bpc); } // this sucks if (gzip_tables) { table_name.append(".gz"); gztable->open(table_name.c_str()); table = gztable; } else { ftable->open(table_name.c_str()); table = ftable; } if(iparams.getName(i); } else { *table << "T_" << thrash->params.getName(i-bpc); } int header = true; // cout << ccache.run_params[i]->current << endl; do { std::string result_name("results/"); result_name += bench->result_filename() + "-" + thrash->result_filename(); // cout << result_name << endl; ifstream result(result_name.c_str()); string r; if (getline(result, r)) { if (header) { *table << '\t' << r << endl; header = false; } } int filterleft = 0; int lines = 0; while (getline(result, r)) { // cout << "."; if ((filter > 0) && (lines % filter == 0)) { filterleft = random() % filter; } if (filterleft == 0) { if (iparams.getCurrentParam(i)->print_current(*table, false); bench->params.printCurrentValue(*table, i, false); } else { //thrash->get_run_param(i-bpc)->print_current(*table, false); thrash->params.printCurrentValue(*table, i-bpc, false); } *table << '\t' << r << endl; } if (filter > 0) { filterleft--; } lines++; } // cout << endl; result.close(); j++; } while ((iparams.advanceOne(i):thrash->params.advanceOne(i-bpc)); // this sucks too if (gzip_tables) { gztable->close(); } else { ftable->close(); } if (j <= 1) { // cout << "deleting table" << endl; unlink(table_name.c_str()); } } while (thrash->advance_params(td)); } while (bench->advance_params(bd)); } cout << "tables created" << endl; delete gztable; delete ftable; } void RibPlot::plot_default(const string & div_param, const string & mult_param, const string & x_param, bool column_lines) { mkdir("png", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); mkdir("R", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); int bpc = bench->params.count(); int tpc = thrash->params.count(); // iterate over parameters to plot on x axis for (int i = 0; i < bpc + tpc; i++) { int bd = (iparams.setCurrentOrder(-1); thrash->params.setCurrentOrder(-1); bench->params.resetAll(); thrash->params.resetAll(); bench->params.setCurrentOrder(-2); thrash->params.setCurrentOrder(-2); cout << "param_depth:" << i << endl; if (!(iparams.advanceOneCheck(i):thrash->params.advanceOneCheck(i-bpc))) { continue; } // the param we plot on x axis string param_name = (iparams.getName(i):"T_" + thrash->params.getName(i-bpc)); // skip this param if x_param is specified and different if (x_param != "" && x_param != param_name) { cout << "skipping " << param_name << endl; continue; } string r_scriptname("R/" + ((iparams.getName(i):("T_" + thrash->params.getName(i-bpc))) + ".R"); r_script.open(r_scriptname.c_str()); r_script << "# created by:" << endl << "# " << cmdLine << endl << endl; if (column_lines) { copyScript("lines.R"); r_script << "tbls <- list()" << endl; r_script << "LGNDS <- array()" << endl; r_script << "colnames <- list()" << endl; } else { copyScript("boxplot.R"); } // iterate over all parameter combinations with the x axis param fixed while (bench->advance_params(bd)) { while (thrash->advance_params(td)) { bench->params.resetAll(); thrash->params.resetAll(); std::string table_name("tables/"); string name = ""; if (iparams.getName(bd) + "-"; name += bench->table_filename(bd) + "-" + thrash->table_filename(td); } else { name += "T_" + thrash->params.getName(td) + "-"; name += bench->table_filename(bd) + "-" + thrash->table_filename(td); } table_name += name; if(iparams.resetOne(i); } else { thrash->params.resetOne(i-bpc); } r_script << "tbl <- read.table(" << gz_table(table_name, gzip_tables) << ", header=TRUE)" << endl << endl; if (column_lines) { if (postscript) { r_script << "my_postscript()" << endl << endl; } else { r_script << "png(\"png/" << name << ".png\", width=1024, height=768)" << endl << endl; } } // counter of columns for linesplot of columns int col = 1; // iterate over columns for (list::iterator it = colNames.begin(); it != colNames.end(); it++) { string colname = it->resultHeader; string colEvent = it->papiEvent; string colnamedesc; std::string png_name("png/" + colname + "-" + name); #ifdef ENABLE_PAPI int event; int retval; PAPI_event_info_t event_info; #endif // PAPI event name for obtaining description string evname = it->papiEvent; #ifdef ENABLE_PAPI if ((retval = PAPI_event_name_to_code((char *)evname.c_str(), &event)) != PAPI_OK) { cerr << "PAPI_event_name_to_code(" << evname << "): " << PAPI_strerror(retval) << endl; } else if ((retval = PAPI_get_event_info(event, &event_info)) != PAPI_OK) { cerr << "Error getting event info for event " << evname << ": " << PAPI_strerror(retval) << endl; } else { colnamedesc = string(" (") + event_info.long_descr + ")"; } #endif // divide the results by values of div_params mult_div(ACTION_DIV, colname, div_param, bd, td); // multiply the results by mult_par value mult_div(ACTION_MULT, colname, mult_param, bd, td); if (column_lines) { r_script << "tbls[[" << col << "]] <- tbl" << endl << endl; r_script << "LGNDS[" << col << "] <- \"" << colEvent << "\"" << endl << endl; r_script << "colnames[[" << col << "]] <- \"" << colname << "\"" << endl; } else { if (postscript) { r_script << "my_postscript()" << endl << endl; } else { r_script << "png(\"" << png_name << ".png\", width=1024, height=768)" << endl << endl; } r_script << endl; if (postscript) { r_script << "MAIN_TITLE=\"\"" << endl; r_script << "SUB_TITLE=\"\"" << endl; } else { r_script << "MAIN_TITLE=\"" << colname << colnamedesc << " dependency on " << param_name << "\"" << endl; r_script << "SUB_TITLE=\"" << bench->params.tableSubtitle(bd) << ", " << thrash->params.tableSubtitle(td) << "\"" << endl; } r_script << "XLAB=\"" << param_name << "\"" << endl; r_script << "YLAB=\"" << colname << " [events/clocks per access average]\"" << endl; r_script << endl; r_script << "rib.boxplot(tbl, \"" << param_name << "\", \"" << colname << "\", \"" << colnamedesc << "\", MAIN_TITLE, SUB_TITLE, XLAB, YLAB, \"test.stat\")" << endl; r_script << "dev.off()" << endl << endl; } col++; } // end (iterate over columns) if (column_lines) { r_script << endl; if (postscript) { r_script << "MAIN_TITLE=\"\"" << endl; r_script << "SUB_TITLE=\"\"" << endl; } else { r_script << "MAIN_TITLE=\"Event counters dependency on " << param_name << "\"" << endl; r_script << "SUB_TITLE=\"" << bench->params.tableSubtitle(bd) << ", " << thrash->params.tableSubtitle(td) << "\"" << endl; } r_script << "LEGEND_TITLE=\"Event counters\"" << endl; r_script << "XLAB=\"" << param_name << "\"" << endl; r_script << "YLAB=\"Event counter values [events per access average]\"" << endl; r_script << endl; r_script << "rib.linesplot(tbls, colnames, LGNDS, \"" << param_name << "\", LEGEND_TITLE, " << col << ", " << 0 << ", " << (nocolor ? "1" : "0") << ", \"" << "\", MAIN_TITLE, SUB_TITLE, XLAB, YLAB)" << endl; r_script << "dev.off()" << endl << endl; } } } r_script << "q(\"no\")" << endl; r_script.close(); if (!postscript) { invoke_R(r_scriptname); } } // alltable.close(); } int RibPlot::param_depth(const std::string & param_name, bool strict) { const string ts = "T_"; int depth; // distinguish between column of benchmark/thrasher if (param_name.compare(0, ts.length(), ts) == 0) { depth = thrash->params.getOrder(param_name.substr(2, param_name.length() - 2)) + bench->params.count(); } else { depth = bench->params.getOrder(param_name); } if (strict && depth == -1) { cerr << "unknown benchmark parameter: " << param_name << endl; exit(EXIT_FAILURE); } return depth; } void RibPlot::plot_lines(const string & x_param, const string & lines_param, const plot_function fnc, const string & ratio_val, const bool legend, const string & colname) { const int param_x = param_depth(x_param, true); const int param_lines = param_depth(lines_param, true); mkdir("png", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); mkdir("png/lines", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); mkdir("R", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); int bpc = bench->params.count(); // int tpc = thrash->param_count(); int bpx = param_x < bpc ? param_x : -1; int bpl = param_lines < bpc ? param_lines : -1; int tpx = param_x >= bpc ? param_x - bpc : -1; int tpl = param_lines >= bpc ? param_lines - bpc : -1; string param_x_name = param_x < bpc ? bench->params.getName(param_x) : "T_" + thrash->params.getName(param_x - bpc); string param_lines_name = param_lines < bpc ? bench->params.getName(param_lines) : "T_" + thrash->params.getName(param_lines - bpc); // cout << param_x_name << endl << param_lines_name << endl; string r_scriptname("R/lines." + colname + "." + param_x_name + "." + param_lines_name + ".R"); r_script.open(r_scriptname.c_str()); r_script << "# created by:" << endl << "# " << cmdLine << endl << endl; copyScript("lines.R"); bench->params.setCurrentOrder(-1); thrash->params.setCurrentOrder(-1); bench->params.resetAll(); thrash->params.resetAll(); do { do { bench->params.resetAll(); thrash->params.resetAll(); std::string png_name("png/lines/" + colname + "-"); string fnname; switch (fnc) { case BLANK: fnname = ""; break; case MULTIPLY: fnname = "mult."; break; case DIVIDE: fnname = "div."; break; case RATIO: fnname = "ratio."; break; } png_name += param_x_name + ".lines." + fnname + param_lines_name + + "-" + bench->params.currentValues(",", false, bpx, bpl) + "-" + thrash->params.currentValues(",", false, tpx, tpl); if (postscript) { r_script << "my_postscript()" << endl; } else { r_script << "png(\"" << png_name << ".png\", width=1024, height=768)" << endl; } r_script << "tbls <- list()" << endl; r_script << "LGNDS <- array()" << endl; if (param_lines < bpc) { bench->params.resetOne(param_lines); } else { thrash->params.resetOne(param_lines - bpc); } int i = 0; do { i++; std::string table_name("tables/"); table_name += param_x_name + "-" + bench->table_filename(bpx) + "-" + thrash->table_filename(tpx); r_script << "tbl <- read.table(" << gz_table(table_name, gzip_tables) << ", header=TRUE)" << endl; // divide the results by values of div_params mult_div(ACTION_DIV, colname, "", bpx, tpx); // multiply the results by mult_par value mult_div(ACTION_MULT, colname, "", bpx, tpx); r_script << "tbls[[" << i << "]] <- tbl" << endl; r_script << "LGNDS[" << i << "] <- \""; if (param_lines < bpc) { //bench->get_run_param(param_lines)->print_current(r_script, true); bench->params.printCurrentValue(r_script, param_lines, true); } else { //thrash->get_run_param(param_lines - bpc)->print_current(r_script, true); thrash->params.printCurrentValue(r_script, param_lines - bpc, true); } r_script << "\"" << endl; } while (param_linesparams.advanceOne(param_lines):thrash->params.advanceOne(param_lines-bpc)); if (postscript) { r_script << "MAIN_TITLE=\"\"" << endl; r_script << "SUB_TITLE=\"\"" << endl; } else { r_script << "MAIN_TITLE=\"" << colname << " dependency on " << param_x_name << "\"" << endl; r_script << "SUB_TITLE=\"" << bench->params.tableSubtitle(bpx, bpl) << ", " << thrash->params.tableSubtitle(tpx, tpl) << "\"" << endl; } r_script << "LEGEND_TITLE=\"" << param_lines_name << "\"" << endl; r_script << "XLAB=\"" << param_x_name << "\"" << endl; r_script << "YLAB=\"" << colname << " [events/clocks per access average]\"" << endl; r_script << endl; r_script << "rib.linesplot(tbls, \"" << colname << "\", LGNDS, \"" << param_x_name << "\", LEGEND_TITLE, " << i << ", " << fnc << ", " << (nocolor ? "1" : "0") << ", " << ratio_val << ", MAIN_TITLE, SUB_TITLE, XLAB, YLAB)" << endl; r_script << "dev.off()" << endl; } while (thrash->advance_params(tpx, tpl)); } while (bench->advance_params(bpx, bpl)); r_script.close(); if (!postscript) { invoke_R(r_scriptname); } } void RibPlot::write_param_combs(list & colnames) { ofstream combs("rib.param_combs"); bool first = true; for (int i = 0; i < bench->params.count(); i++) { if (first) { first = false; } else { combs << "\t"; } combs << bench->params.getName(i); } combs << "\t"; first = true; for (int i = 0; i < thrash->params.count(); i++) { if (first) { first = false; } else { combs << "\t"; } combs << "T_" << thrash->params.getName(i); } combs << endl; while (bench->advance_params(-1)) { bench->params.resetAll(); while (thrash->advance_params(-1)) { thrash->params.resetAll(); bench->params.printValues(combs, "\t"); combs << "\t"; thrash->params.printValues(combs, "\t"); combs << endl; } } combs.close(); first = true; ostringstream os; os << "\""; for (int i = 0; i < bench->params.count(); i++) { if (first) { first = false; } else { os << "\", \""; } os << bench->params.getName(i); } os << "\", \""; first = true; for (int i = 0; i < thrash->params.count(); i++) { if (first) { first = false; } else { os << "\", \""; } os << "T_" << thrash->params.getName(i); } os << "\""; ofstream Rscript("defplot.R", ios::app); Rscript << endl; Rscript << "params <- c(" << os.str() << ")" << endl; Rscript << "bench_name <- \"" << bench->benchmark_name << "\"" << endl; Rscript << "thrash_name <- \"" << thrash->benchmark_name << "\"" << endl; first = false; os.str(""); os << "\""; first = true; for (list::iterator it = colnames.begin(); it != colnames.end(); it++) { if (first) { first = false; } else { os << "\", \""; } os << it->resultHeader; } os << "\""; Rscript << "result_names <- c(" << os.str() << ")" << endl; } int main(int argc, char ** argv) { cout << "Plotting scripts will be loaded from " << RIB_DIR << "/plotscripts" << endl; #ifdef ENABLE_PAPI int r = PAPI_library_init(PAPI_VER_CURRENT); if (r != PAPI_VER_CURRENT && r > 0) { cerr << "PAPI library version mismatch!" << endl; } if (r < 0) { cerr << "PAPI initialization error: " << PAPI_strerror(r) << endl; } // cout << "PAPI version: " << PAPI_VERSION_MAJOR(r) << "." << // PAPI_VERSION_MINOR(r) << "." << PAPI_VERSION_REVISION(r) << endl; #endif map > allparams = parse_ini("rib.ini"); if (allparams.find("benchmark") == allparams.end()) { cerr << "missing [benchmark] section in rib.ini" << endl; exit(EXIT_FAILURE); } // if (allparams.find("thrashing") == allparams.end()) { // cerr << "missing [thrashing] section in rib.ini" << endl; // exit(EXIT_FAILURE); // } map params = allparams.find("global")->second; if (params.find("benchmark") == params.end()) { cerr << "missing benchmark parameter in rib.ini" << endl; exit(EXIT_FAILURE); } if (params.find("thrashing") == params.end()) { cerr << "missing thrashing parameter in rib.ini" << endl; exit(EXIT_FAILURE); } Benchmark * bench = Benchmark::CreateBenchmark(((BenchParameterString *)(*params["benchmark"].begin()))->value); if (!bench) { cerr << "no valid benchmark specified" << endl; exit(1); } bench->initialize_params(allparams.find("benchmark")->second, true, true); ThrashingBenchmark * thrash = ThrashingBenchmark::CreateThrashingBenchmark(((BenchParameterString*)(*params["thrashing"].begin()))->value); if (!bench) { cerr << "no valid thrasher specified" << endl; exit(1); } if (allparams.find("thrashing") != allparams.end()) { thrash->initialize_params(allparams.find("thrashing")->second, true, true); } free_ini(allparams); string div_param = ""; string mult_param = ""; bool alltable = false; RibPlot::plot_function fnc = RibPlot::BLANK; string ratioval = "0"; int filter = 0; // limit plotting only along this param string x_param = ""; // plot lines varying this param string lines_param = ""; // plot legends in lineplot? bool legend = true; // user-specified colname (with -c) or colnames (with -L) to plot string colNamesUser = "ALL"; // plot lines of different columns instead of one boxplot per column bool linesCols = false; RibPlot plotter(bench, thrash); struct option long_opts[] = { {"x-param", required_argument, NULL, 'x'}, {"lines-param", required_argument, NULL, 'l'}, {"lines-cols", required_argument, NULL, 'L'}, {"ratio", required_argument, NULL, 'r'}, {"no-color", no_argument, NULL, 'n'}, {"no-legend", no_argument, NULL, 'N'}, {"column", required_argument, NULL, 'c'}, {"zip-tables", no_argument, NULL, 'z'}, {"no-zip-tables", no_argument, NULL, 'Z'}, {"postscript", no_argument, NULL, 'p'}, {"divide", required_argument, NULL, 'd'}, {"multiply", required_argument, NULL, 'm'}, {"filter", required_argument, NULL, 'F'}, {"alltable", no_argument, NULL, 'a'}, {0, 0, 0, 0} }; while (true) { int c; int opt_index = 0; c = getopt_long(argc, argv, "x:l:L:r:nNc:zZpd:m:F:a", long_opts, &opt_index); if (c == -1) { break; } switch (c) { case 'x': x_param = optarg; break; case 'l': lines_param = optarg; break; case 'L': linesCols = true; colNamesUser = optarg; break; case 'r': fnc = RibPlot::RATIO; ratioval = optarg; break; case 'n': plotter.nocolor = true; break; case 'N': legend = false; break; case 'c': colNamesUser = optarg; break; case 'z': plotter.gzip_tables = true; break; case 'Z': plotter.gzip_tables = false; break; case 'p': plotter.postscript = true; break; case 'd': cout << "dividing by parameter: " << optarg << endl; div_param = optarg; break; case 'F': filter = atoi(optarg); break; case 'a': alltable = true; break; case '?': cerr << "unknown option: " << argv[optind] << endl; exit(EXIT_FAILURE); break; default: cerr << "unexpected getopt_long() result: " << c << endl; exit(EXIT_FAILURE); } } // store the command line ostringstream cmdLineStream; for (int i = 0; i < argc; i++) { cmdLineStream << " " << argv[i]; } plotter.cmdLine = cmdLineStream.str(); // just plot all columns if (colNamesUser == "ALL") { plotter.colNames = bench->get_result_columns(); list col2 = thrash->get_result_columns(); for (list::iterator it = col2.begin(); it != col2.end(); it++) { Benchmark::column_name col = *it; col.resultHeader = "T_" + col.resultHeader; plotter.colNames.push_back(col); } } else { // replace PAPI delimiters : to . replace_chars(colNamesUser, ':', '.'); // colNamesUser are multiple (comma-separated) column names vector colNamesVec = tokenize(colNamesUser, ","); // convert to set for lookups set colNamesSet (colNamesVec.begin(), colNamesVec.end()); // go through all column names declared by benchmark, adding them to the plotter list // only if found in the user-specified list list benchCols = bench->get_result_columns(); for (list::const_iterator it = benchCols.begin(); it != benchCols.end(); it++) { set::iterator it2 = colNamesSet.find(it->resultHeader); if (it2 != colNamesSet.end()) { plotter.colNames.push_back(*it); colNamesSet.erase(it2); } } // similarly with thrasher column names, just prepend with T_ list trashCols = thrash->get_result_columns(); for (list::const_iterator it = trashCols.begin(); it != trashCols.end(); it++) { Benchmark::column_name col = *it; col.resultHeader = "T_" + col.resultHeader; set::iterator it2 = colNamesSet.find(col.resultHeader); if (it2 != colNamesSet.end()) { plotter.colNames.push_back(col); colNamesSet.erase(it2); } } // anything that's now left in the set are result columns that user specified but are not there set::iterator itSet = colNamesSet.begin(); if (itSet != colNamesSet.end()) { cerr << "error: following column names not found:" << endl; while (itSet != colNamesSet.end()) { cerr << *itSet << endl; itSet++; } exit (EXIT_FAILURE); } } if (alltable) { plotter.create_alltable(); exit(EXIT_SUCCESS); } else { plotter.create_tables(filter); } if (lines_param == "") { plotter.plot_default(div_param, mult_param, x_param, linesCols); } else { cout << "lines" << endl; // TODO: convert this to getopt and make it work again // if (false) { // // string fnc_arg(argv[4]); // // if (fnc_arg == "normal") { // fnc = RibPlot::BLANK; // } else if (fnc_arg == "divide") { // fnc = RibPlot::DIVIDE; // } else if (fnc_arg == "multiply") { // fnc = RibPlot::MULTIPLY; // } else if (fnc_arg == "ratio") { // fnc = RibPlot::RATIO; // ratioval = argv[5]; // } else { // cerr << "wrong function param " << fnc_arg << ", must be blank, divide, multiply or ratio x" << endl; // exit(1); // } // // } for (list::iterator it = plotter.colNames.begin(); it != plotter.colNames.end(); it++) { cout << it->resultHeader << endl; plotter.plot_lines(x_param, lines_param, fnc, ratioval, legend, it->resultHeader); } } }