"Fossies" - the Fresh Open Source Software Archive

Member "bonnie++-2.00a/bon_csv2html.cpp" (22 Sep 2020, 15030 Bytes) of package /linux/privat/bonnie++-2.00a.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "bon_csv2html.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.98_vs_2.00a.

    1 #include "bonnie.h"
    2 #include <cstdlib>
    3 #include <stdio.h>
    4 #include <vector>
    5 #include <string.h>
    6 #include <math.h>
    7 
    8 // Maximum number of items expected on a csv line
    9 #define MAX_ITEMS 50
   10 using namespace std;
   11 typedef vector<PCCHAR> STR_VEC;
   12 
   13 vector<STR_VEC> data;
   14 typedef PCCHAR * PPCCHAR;
   15 PPCCHAR * props;
   16 
   17 // Print the start of the HTML file
   18 // return the number of columns space in the middle
   19 int header();
   20 // Splits a line of text (CSV format) by commas and adds it to the list to
   21 // process later.  Doesn't keep any pointers to the buf...
   22 void read_in(CPCCHAR buf);
   23 // print line in the specified line from columns start..end as a line of a
   24 // HTML table
   25 void print_a_line(int num, int start, int end);
   26 // print a single item of data
   27 void print_item(int num, int item, CPCCHAR extra = NULL);
   28 // Print the end of the HTML file
   29 void footer();
   30 // Calculate the colors for backgrounds
   31 void calc_vals();
   32 // Returns a string representation of a color that maps to the value.  The
   33 // range of values is 0..range_col and val is the value.  If reverse is set
   34 // then low values are green and high values are red.
   35 PCCHAR get_col(double range_col, double val, bool reverse, CPCCHAR extra);
   36 
   37 typedef enum { eNoCols, eSpeed, eCPU, eLatency } VALS_TYPE;
   38 const VALS_TYPE vals[MAX_ITEMS] =
   39   { eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,
   40     eNoCols,eNoCols,eNoCols,eNoCols,eNoCols,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,eSpeed,eCPU,
   41     eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency,eLatency };
   42 
   43 bool col_used[MAX_ITEMS];
   44 #define COL_NAME 2
   45 #define COL_CONCURRENCY 3
   46 #define COL_FILE_SIZE 5
   47 #define COL_DATA_CHUNK_SIZE 6
   48 #define COL_PUTC 9
   49 #define COL_PUT_BLOCK 11
   50 #define COL_REWRITE 13
   51 #define COL_GET_BLOCK 17
   52 #define COL_NUM_FILES 21
   53 #define COL_MAX_SIZE 22
   54 #define COL_MIN_SIZE 23
   55 #define COL_NUM_DIRS 24
   56 #define COL_FILE_CHUNK_SIZE 25
   57 #define COL_RAN_DEL_CPU 37
   58 #define COL_PUTC_LATENCY 38
   59 #define COL_SEEKS_LATENCY 43
   60 #define COL_SEQ_CREATE_LATENCY 44
   61 #define COL_RAN_DEL_LATENCY 49
   62 
   63 void usage()
   64 {
   65   exit(1);
   66 }
   67 
   68 int main(int argc, char **argv)
   69 {
   70   unsigned int i;
   71   for(i = 0; i < MAX_ITEMS; i++)
   72     col_used[i] = false;
   73 
   74   char buf[1024];
   75 
   76   FILE *fp = NULL;
   77   if(argc > 1)
   78   {
   79     fp = fopen(argv[1], "r");
   80     if(!fp)
   81       usage();
   82   }
   83   while(fgets(buf, sizeof(buf), fp ? fp : stdin))
   84   {
   85     buf[sizeof(buf) - 1] = '\0';
   86     strtok(buf, "\r\n");
   87     read_in(buf);
   88   }
   89 
   90   props = new PPCCHAR[data.size()];
   91   for(i = 0; i < data.size(); i++)
   92   {
   93     props[i] = new PCCHAR[MAX_ITEMS];
   94     props[i][0] = NULL;
   95     props[i][1] = NULL;
   96     props[i][COL_NAME] = "bgcolor=\"#FFFFFF\" class=\"rowheader\"><font size=+1";
   97     int j;
   98     for(j = COL_CONCURRENCY; j < MAX_ITEMS; j++)
   99     {
  100       if( (j >= COL_NUM_FILES && j <= COL_FILE_CHUNK_SIZE) || j <= COL_DATA_CHUNK_SIZE )
  101       {
  102         props[i][j] = "class=\"size\" bgcolor=\"#FFFFFF\"";
  103       }
  104       else
  105       {
  106         props[i][j] = NULL;
  107       }
  108     }
  109   }
  110   calc_vals();
  111   int mid_width = header();
  112   for(i = 0; i < data.size(); i++)
  113   {
  114 // First print the average speed line
  115     printf("<tr>");
  116     print_item(i, COL_NAME, "rowspan=\"2\"");
  117     if(col_used[COL_CONCURRENCY] == true)
  118       print_item(i, COL_CONCURRENCY);
  119     print_item(i, COL_FILE_SIZE); // file_size
  120     if(col_used[COL_DATA_CHUNK_SIZE] == true)
  121       print_item(i, COL_DATA_CHUNK_SIZE);
  122     print_a_line(i, COL_PUTC, COL_NUM_FILES);
  123     if(col_used[COL_MAX_SIZE])
  124       print_item(i, COL_MAX_SIZE);
  125     if(col_used[COL_MIN_SIZE])
  126       print_item(i, COL_MIN_SIZE);
  127     if(col_used[COL_NUM_DIRS])
  128       print_item(i, COL_NUM_DIRS);
  129     if(col_used[COL_FILE_CHUNK_SIZE])
  130       print_item(i, COL_FILE_CHUNK_SIZE);
  131     print_a_line(i, COL_FILE_CHUNK_SIZE + 1, COL_RAN_DEL_CPU);
  132     printf("</tr>\n");
  133 // Now print the latency line
  134     printf("<tr>");
  135     int lat_width = 1;
  136     if(col_used[COL_DATA_CHUNK_SIZE] == true)
  137       lat_width++;
  138     if(col_used[COL_CONCURRENCY] == true)
  139       lat_width++;
  140     printf("<td class=\"size\" bgcolor=\"#FFFFFF\" colspan=\"%d\">Latency</td>"
  141          , lat_width);
  142     print_a_line(i, COL_PUTC_LATENCY, COL_SEEKS_LATENCY);
  143     int bef_lat_width;
  144     lat_width = 1;
  145     if(mid_width > 1)
  146       lat_width = 2;
  147     bef_lat_width = mid_width - lat_width;
  148     if(bef_lat_width)
  149       printf("<td colspan=\"%d\"></td>", bef_lat_width);
  150     printf("<td class=\"size\" bgcolor=\"#FFFFFF\" colspan=\"%d\">Latency</td>", lat_width);
  151     print_a_line(i, COL_SEQ_CREATE_LATENCY, COL_RAN_DEL_LATENCY);
  152     printf("</tr>\n");
  153   }
  154   footer();
  155   return 0;
  156 }
  157 
  158 typedef struct { double val; int pos; int col_ind; } ITEM;
  159 typedef ITEM * PITEM;
  160 
  161 int compar(const void *a, const void *b)
  162 {
  163   double a1 = PITEM(a)->val;
  164   double b1 = PITEM(b)->val;
  165   if(a1 < b1)
  166     return -1;
  167   if(a1 > b1)
  168     return 1;
  169   return 0;
  170 }
  171 
  172 void calc_vals()
  173 {
  174   ITEM *arr = new ITEM[data.size()];
  175   for(unsigned int column_ind = 0; column_ind < MAX_ITEMS; column_ind++)
  176   {
  177     switch(vals[column_ind])
  178     {
  179     case eNoCols:
  180     {
  181       for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
  182       {
  183         if(column_ind == COL_CONCURRENCY)
  184         {
  185           if(data[row_ind][column_ind] && strcmp("1", data[row_ind][column_ind]))
  186             col_used[column_ind] = true;
  187         }
  188         else
  189         {
  190           if(data[row_ind][column_ind] && strlen(data[row_ind][column_ind]))
  191             col_used[column_ind] = true;
  192         }
  193       }
  194     }
  195     break;
  196     case eCPU:
  197     {
  198       for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
  199       {
  200         double work, cpu;
  201         arr[row_ind].val = 0.0;
  202         if(data[row_ind].size() > column_ind
  203          && sscanf(data[row_ind][column_ind - 1], "%lf", &work) == 1
  204          && sscanf(data[row_ind][column_ind], "%lf", &cpu) == 1)
  205         {
  206           arr[row_ind].val = cpu / work;
  207         }
  208         arr[row_ind].pos = row_ind;
  209       }
  210       qsort(arr, data.size(), sizeof(ITEM), compar);
  211       int col_count = -1;
  212       double min_col = -1.0, max_col = -1.0;
  213       for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  214       {
  215         // if item is different from previous or if the first row
  216         // (sort_ind == 0) then increment col count
  217         if(sort_ind == 0 || arr[sort_ind].val != arr[sort_ind - 1].val)
  218         {
  219           if(arr[sort_ind].val != 0.0)
  220           {
  221             col_count++;
  222             if(min_col == -1.0)
  223               min_col = arr[sort_ind].val;
  224             else
  225               min_col = min(arr[sort_ind].val, min_col);
  226             max_col = max(max_col, arr[sort_ind].val);
  227           }
  228         }
  229         arr[sort_ind].col_ind = col_count;
  230       }
  231       // if more than 1 line has data then calculate colors
  232       if(col_count > 0)
  233       {
  234         double divisor = max_col / min_col;
  235         if(divisor < 2.0)
  236         {
  237           double mult = sqrt(2.0 / divisor);
  238           max_col *= mult;
  239           min_col /= mult;
  240         }
  241         double range_col = max_col - min_col;
  242         for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  243         {
  244           if(arr[sort_ind].col_ind > -1)
  245           {
  246             props[arr[sort_ind].pos][column_ind]
  247                   = get_col(range_col, arr[sort_ind].val - min_col, true, "");
  248           }
  249         }
  250       }
  251       else
  252       {
  253         for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  254         {
  255           if(vals[column_ind] == eLatency)
  256           {
  257             props[sort_ind][column_ind] = "colspan=\"2\"";
  258           }
  259         }
  260       }
  261     }
  262     break;
  263     case eSpeed:
  264     case eLatency:
  265     {
  266       for(unsigned int row_ind = 0; row_ind < data.size(); row_ind++)
  267       {
  268         arr[row_ind].val = 0.0;
  269         if(data[row_ind].size() <= column_ind
  270          || sscanf(data[row_ind][column_ind], "%lf", &arr[row_ind].val) == 0)
  271           arr[row_ind].val = 0.0;
  272         if(vals[column_ind] == eLatency && arr[row_ind].val != 0.0)
  273         {
  274           if(strstr(data[row_ind][column_ind], "ms"))
  275             arr[row_ind].val *= 1000.0;
  276           else if(!strstr(data[row_ind][column_ind], "us"))
  277             arr[row_ind].val *= 1000000.0; // is !us && !ms then secs!
  278         }
  279         arr[row_ind].pos = row_ind;
  280       }
  281       qsort(arr, data.size(), sizeof(ITEM), compar);
  282       int col_count = -1;
  283       double min_col = -1.0, max_col = -1.0;
  284       for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  285       {
  286         // if item is different from previous or if the first row
  287         // (sort_ind == 0) then increment col count
  288         if(sort_ind == 0 || arr[sort_ind].val != arr[sort_ind - 1].val)
  289         {
  290           if(arr[sort_ind].val != 0.0)
  291           {
  292             col_count++;
  293             if(min_col == -1.0)
  294               min_col = arr[sort_ind].val;
  295             else
  296               min_col = min(arr[sort_ind].val, min_col);
  297             max_col = max(max_col, arr[sort_ind].val);
  298           }
  299         }
  300         arr[sort_ind].col_ind = col_count;
  301       }
  302       // if more than 1 line has data then calculate colors
  303       if(col_count > 0)
  304       {
  305         double divisor = max_col / min_col;
  306         if(divisor < 2.0)
  307         {
  308           double mult = sqrt(2.0 / divisor);
  309           max_col *= mult;
  310           min_col /= mult;
  311         }
  312         double range_col = max_col - min_col;
  313         for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  314         {
  315           if(arr[sort_ind].col_ind > -1)
  316           {
  317             bool reverse = false;
  318             PCCHAR extra = "";
  319             if(vals[column_ind] != eSpeed)
  320             {
  321               reverse = true;
  322               extra = " colspan=\"2\"";
  323             }
  324             props[arr[sort_ind].pos][column_ind]
  325                   = get_col(range_col, arr[sort_ind].val - min_col, reverse, extra);
  326           }
  327           else if(vals[column_ind] != eSpeed)
  328           {
  329             props[arr[sort_ind].pos][column_ind] = "colspan=\"2\"";
  330           }
  331         }
  332       }
  333       else
  334       {
  335         for(unsigned int sort_ind = 0; sort_ind < data.size(); sort_ind++)
  336         {
  337           if(vals[column_ind] == eLatency)
  338           {
  339             props[sort_ind][column_ind] = "colspan=\"2\"";
  340           }
  341         }
  342       }
  343     }
  344     break;
  345     } // end switch
  346   }
  347 }
  348 
  349 PCCHAR get_col(double range_col, double val, bool reverse, CPCCHAR extra)
  350 {
  351   if(reverse)
  352     val = range_col - val;
  353   const int buf_len = 256;
  354   PCHAR buf = new char[buf_len];
  355   int green = int(255.0 * val / range_col);
  356   green = min(green, 255);
  357   int red = 255 - green;
  358   _snprintf(buf
  359 #ifndef NO_SNPRINTF
  360           , buf_len
  361 #endif
  362           , "bgcolor=\"#%02X%02X00\"%s", red, green, extra);
  363   buf[buf_len - 1] = '\0';
  364   return buf;
  365 }
  366 
  367 void heading(const char * const head);
  368 
  369 int header()
  370 {
  371   int vers_width = 2;
  372   if(col_used[COL_DATA_CHUNK_SIZE] == true)
  373     vers_width++;
  374   if(col_used[COL_CONCURRENCY] == true)
  375     vers_width++;
  376   int mid_width = 1;
  377   if(col_used[COL_MAX_SIZE])
  378     mid_width++;
  379   if(col_used[COL_MIN_SIZE])
  380     mid_width++;
  381   if(col_used[COL_NUM_DIRS])
  382     mid_width++;
  383   if(col_used[COL_FILE_CHUNK_SIZE])
  384     mid_width++;
  385   printf("<!DOCTYPE html PUBLIC \"-//W3C//Dtd XHTML 1.0 Strict//EN\" \"http://www.w3.org/tr/xhtml1/Dtd/xhtml1-strict.dtd\">"
  386 "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
  387 "<head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" /><title>Bonnie++ Benchmark results</title>"
  388 "<style type=\"text/css\">"
  389 "td.header {text-align: center; background-color: \"#CCFFFF\" }"
  390 "td.rowheader {text-align: center; background-color: \"#CCCFFF\" }"
  391 "td.size {text-align: center; background-color: \"#CCCFFF\" }"
  392 "td.ksec {text-align: center; fontstyle: italic }"
  393 "</style></head>"
  394 "<body>"
  395 "<table border=\"3\" cellpadding=\"2\" cellspacing=\"1\">"
  396 "<tr><td colspan=\"%d\" class=\"header\"><font size=+1><b>"
  397 "Version " BON_VERSION
  398 "</b></font></td>"
  399 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Sequential Output</b></font></td>"
  400 "<td colspan=\"4\" class=\"header\"><font size=+2><b>Sequential Input</b></font></td>"
  401 "<td colspan=\"2\" rowspan=\"2\" class=\"header\"><font size=+2><b>Random<br>Seeks</b></font></td>"
  402 "<td colspan=\"%d\" class=\"header\"></td>"
  403 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Sequential Create</b></font></td>"
  404 "<td colspan=\"6\" class=\"header\"><font size=+2><b>Random Create</b></font></td>"
  405 "</tr>\n"
  406 "<tr>", vers_width, mid_width);
  407   if(col_used[COL_CONCURRENCY] == true)
  408     printf("<td colspan=\"2\">Concurrency</td>");
  409   else
  410     printf("<td></td>");
  411   printf("<td>Size</td>");
  412   if(col_used[COL_DATA_CHUNK_SIZE] == true)
  413     printf("<td>Chunk Size</td>");
  414   heading("Per Char"); heading("Block"); heading("Rewrite");
  415   heading("Per Char"); heading("Block");
  416   printf("<td>Num Files</td>");
  417   if(col_used[COL_MAX_SIZE])
  418     printf("<td>Max Size</td>");
  419   if(col_used[COL_MIN_SIZE])
  420     printf("<td>Min Size</td>");
  421   if(col_used[COL_NUM_DIRS])
  422     printf("<td>Num Dirs</td>");
  423   if(col_used[COL_FILE_CHUNK_SIZE])
  424     printf("<td>Chunk Size</td>");
  425   heading("Create"); heading("Read"); heading("Delete");
  426   heading("Create"); heading("Read"); heading("Delete");
  427   printf("</tr>");
  428 
  429   printf("<tr><td colspan=\"%d\"></td>", vers_width);
  430 
  431   int i;
  432   CPCCHAR ksec_form = "<td class=\"ksec\"><font size=-2>%s/sec</font></td>"
  433                       "<td class=\"ksec\"><font size=-2>%% CPU</font></td>";
  434   for(i = 0; i < 5; i++)
  435   {
  436     printf(ksec_form, "M");
  437   }
  438   printf(ksec_form, "");
  439   printf("<td colspan=\"%d\"></td>", mid_width);
  440   for(i = 0; i < 6; i++)
  441   {
  442     printf(ksec_form, "");
  443   }
  444   printf("</tr>\n");
  445   return mid_width;
  446 }
  447 
  448 void heading(const char * const head)
  449 {
  450   printf("<td colspan=\"2\">%s</td>", head);
  451 }
  452 
  453 void footer()
  454 {
  455   printf("</table>\n</body></html>\n");
  456 }
  457 
  458 STR_VEC split(CPCCHAR delim, CPCCHAR buf)
  459 {
  460   STR_VEC arr;
  461   char *tmp = strdup(buf);
  462   while(1)
  463   {
  464     arr.push_back(tmp);
  465     tmp = strstr(tmp, delim);
  466     if(!tmp)
  467       break;
  468     *tmp = '\0';
  469     tmp += strlen(delim);
  470   }
  471   return arr;
  472 }
  473 
  474 void read_in(CPCCHAR buf)
  475 {
  476   STR_VEC arr = split(",", buf);
  477   if(strcmp(arr[0], CSV_VERSION) )
  478   {
  479     if(strncmp(arr[0], "format_version", 14))
  480       fprintf(stderr, "Can't process: %s\n", buf);
  481     free((void *)arr[0]);
  482     return;
  483   }
  484   data.push_back(arr);
  485 }
  486 
  487 void print_item(int num, int item, CPCCHAR extra)
  488 {
  489   PCCHAR line_data;
  490   char buf[1024];
  491   if(int(data[num].size()) > item)
  492   {
  493     line_data = data[num][item];
  494     switch(item)
  495     {
  496     case COL_PUT_BLOCK:
  497     case COL_REWRITE:
  498     case COL_GET_BLOCK:
  499       int tmp = (atoi(line_data) + 512) / 1024;
  500       snprintf(buf, sizeof(buf), "%d", tmp);
  501       line_data = buf;
  502     }
  503   }
  504   else
  505     line_data = "";
  506   printf("<td");
  507   if(extra)
  508     printf(" %s", extra);
  509   if(props[num][item])
  510     printf(" %s", props[num][item]);
  511   printf(">%s</td>", line_data);
  512 }
  513 
  514 void print_a_line(int num, int start, int end)
  515 {
  516   int i;
  517   for(i = start; i <= end; i++)
  518   {
  519     print_item(num, i);
  520   }
  521 }