in wb/wb.c [1862:2216]
static void output_results(int sig)
{
double timetaken;
if (sig) {
lasttime = apr_time_now(); /* record final time if interrupted */
}
timetaken = (double) (lasttime - start) / APR_USEC_PER_SEC;
printf("\n\n");
printf("Server Software: %s\n", servername);
printf("Server Hostname: %s\n", hostname);
printf("Server Port: %hu\n", port);
#ifdef USE_SSL
if (is_ssl && ssl_info) {
printf("SSL/TLS Protocol: %s\n", ssl_info);
}
if (is_ssl && ssl_tmp_key) {
printf("Server Temp Key: %s\n", ssl_tmp_key);
}
#ifdef HAVE_TLSEXT
if (is_ssl && tls_sni) {
printf("TLS Server Name: %s\n", tls_sni);
}
#endif
#endif
printf("\n");
printf("Document Path: %s\n", path);
if (nolength)
printf("Document Length: Variable\n");
else
printf("Document Length: %" APR_SIZE_T_FMT " bytes\n", doclen);
printf("\n");
printf("Concurrency Level: %d\n", concurrency);
printf("Time taken for tests: %.3f seconds\n", timetaken);
printf("Complete requests: %d\n", done);
#ifdef _WAF_BENCH_ // print color text for bad results
//if (bad > 0)
printf("\033[0;31m"); // RED color for failed requests
#endif //_WAF_BENCH_ print color text
printf("Failed requests: %d\n", bad);
if (bad)
printf(" (Connect: %d, Receive: %d, Length: %d, Exceptions: %d)\n",
err_conn, err_recv, err_length, err_except);
if (epipe)
printf("Write errors: %d\n", epipe);
if (err_response) {
printf("Non-2xx responses: %d\n", err_response);
for (unsigned int i = 0; i < sizeof(respcodes) / sizeof(respcodes[0]); i++) {
if (respcodes[i] > 0) {
printf("%d responses: %d\n", i, respcodes[i]);
}
}
}
#ifdef _WAF_BENCH_ // return to no-color
//if (bad > 0)
printf("\033[0m"); // no color
#endif //_WAF_BENCH_ return to no-color
if (keepalive)
printf("Keep-Alive requests: %d\n", doneka);
printf("Total transferred: %" APR_INT64_T_FMT " bytes\n", totalread);
if (send_body)
printf("Total body sent: %" APR_INT64_T_FMT "\n",
totalposted);
printf("HTML transferred: %" APR_INT64_T_FMT " bytes\n", totalbread);
/* avoid divide by zero */
if (timetaken && done) {
#ifdef _WAF_BENCH_ // print color text
printf("\033[1;33m"); // Yellow color for RPS numbers
#endif //_WAF_BENCH_ print color text
printf("Requests per second: %.2f [#/sec] (mean)\n",
(double) done / timetaken);
#ifdef _WAF_BENCH_ // print no-color text
printf("\033[0m"); // no color
#endif //_WAF_BENCH_ print no-color text
printf("Time per request: %.3f [ms] (mean)\n",
(double) concurrency * timetaken * 1000 / done);
#ifdef _WAF_BENCH_ // when concurrency == 1, we can avoid print duplicated results
if (concurrency > 1)
#endif //_WAF_BENCH_ when concurrency == 1, we can avoid print duplicated results
printf("Time per request: %.3f [ms] (mean, across all concurrent requests)\n",
(double) timetaken * 1000 / done);
printf("Transfer rate: %.2f [Kbytes/sec] received\n",
(double) totalread / 1024 / timetaken);
if (send_body) {
printf(" %.2f kb/s sent\n",
(double) totalposted / 1024 / timetaken);
printf(" %.2f kb/s total\n",
(double) (totalread + totalposted) / 1024 / timetaken);
}
}
#ifdef _WAF_BENCH_ // real sent# might be greater than g_stats_window;
done = ap_min(done, g_stats_window);
printf("Total samples of stats: %d",done);
#endif //_WAF_BENCH_ real sent# might be greater than g_stats_window;
if (done > 0) {
/* work out connection times */
int i;
apr_time_t totalcon = 0, total = 0, totald = 0, totalwait = 0;
apr_time_t meancon, meantot, meand, meanwait;
apr_interval_time_t mincon = AB_MAX, mintot = AB_MAX, mind = AB_MAX,
minwait = AB_MAX;
apr_interval_time_t maxcon = 0, maxtot = 0, maxd = 0, maxwait = 0;
apr_interval_time_t mediancon = 0, mediantot = 0, mediand = 0, medianwait = 0;
double sdtot = 0, sdcon = 0, sdd = 0, sdwait = 0;
for (i = 0; i < done; i++) {
struct data *s = &stats[i];
mincon = ap_min(mincon, s->ctime);
mintot = ap_min(mintot, s->time);
mind = ap_min(mind, s->time - s->ctime);
minwait = ap_min(minwait, s->waittime);
maxcon = ap_max(maxcon, s->ctime);
maxtot = ap_max(maxtot, s->time);
maxd = ap_max(maxd, s->time - s->ctime);
maxwait = ap_max(maxwait, s->waittime);
totalcon += s->ctime;
total += s->time;
totald += s->time - s->ctime;
totalwait += s->waittime;
}
meancon = totalcon / done;
meantot = total / done;
meand = totald / done;
meanwait = totalwait / done;
/* calculating the sample variance: the sum of the squared deviations, divided by n-1 */
for (i = 0; i < done; i++) {
struct data *s = &stats[i];
double a;
a = ((double)s->time - meantot);
sdtot += a * a;
a = ((double)s->ctime - meancon);
sdcon += a * a;
a = ((double)s->time - (double)s->ctime - meand);
sdd += a * a;
a = ((double)s->waittime - meanwait);
sdwait += a * a;
}
sdtot = (done > 1) ? sqrt(sdtot / (done - 1)) : 0;
sdcon = (done > 1) ? sqrt(sdcon / (done - 1)) : 0;
sdd = (done > 1) ? sqrt(sdd / (done - 1)) : 0;
sdwait = (done > 1) ? sqrt(sdwait / (done - 1)) : 0;
/*
* XXX: what is better; this hideous cast of the compradre function; or
* the four warnings during compile ? dirkx just does not know and
* hates both/
*/
qsort(stats, done, sizeof(struct data),
(int (*) (const void *, const void *)) compradre);
if ((done > 1) && (done % 2))
mediancon = (stats[done / 2].ctime + stats[done / 2 + 1].ctime) / 2;
else
mediancon = stats[done / 2].ctime;
qsort(stats, done, sizeof(struct data),
(int (*) (const void *, const void *)) compri);
if ((done > 1) && (done % 2))
mediand = (stats[done / 2].time + stats[done / 2 + 1].time \
-stats[done / 2].ctime - stats[done / 2 + 1].ctime) / 2;
else
mediand = stats[done / 2].time - stats[done / 2].ctime;
qsort(stats, done, sizeof(struct data),
(int (*) (const void *, const void *)) compwait);
if ((done > 1) && (done % 2))
medianwait = (stats[done / 2].waittime + stats[done / 2 + 1].waittime) / 2;
else
medianwait = stats[done / 2].waittime;
qsort(stats, done, sizeof(struct data),
(int (*) (const void *, const void *)) comprando);
if ((done > 1) && (done % 2))
mediantot = (stats[done / 2].time + stats[done / 2 + 1].time) / 2;
else
mediantot = stats[done / 2].time;
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
if (g_us_granularity)
printf("\nConnection Times (us)\n");
else {
#endif // _WAF_BENCH_ // microsec-granularity in output-results
printf("\nConnection Times (ms)\n");
/*
* Reduce stats from apr time to milliseconds
*/
mincon = ap_round_ms(mincon);
mind = ap_round_ms(mind);
minwait = ap_round_ms(minwait);
mintot = ap_round_ms(mintot);
meancon = ap_round_ms(meancon);
meand = ap_round_ms(meand);
meanwait = ap_round_ms(meanwait);
meantot = ap_round_ms(meantot);
mediancon = ap_round_ms(mediancon);
mediand = ap_round_ms(mediand);
medianwait = ap_round_ms(medianwait);
mediantot = ap_round_ms(mediantot);
maxcon = ap_round_ms(maxcon);
maxd = ap_round_ms(maxd);
maxwait = ap_round_ms(maxwait);
maxtot = ap_round_ms(maxtot);
sdcon = ap_double_ms(sdcon);
sdd = ap_double_ms(sdd);
sdwait = ap_double_ms(sdwait);
sdtot = ap_double_ms(sdtot);
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
}
#endif // _WAF_BENCH_ // microsec-granularity in output-results
if (confidence) {
#define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %4" APR_TIME_T_FMT " %5.1f %6" APR_TIME_T_FMT " %7" APR_TIME_T_FMT "\n"
printf(" min mean[+/-sd] median max\n");
printf("Connect: " CONF_FMT_STRING,
mincon, meancon, sdcon, mediancon, maxcon);
printf("Processing: " CONF_FMT_STRING,
mind, meand, sdd, mediand, maxd);
printf("Waiting: " CONF_FMT_STRING,
minwait, meanwait, sdwait, medianwait, maxwait);
printf("Total: " CONF_FMT_STRING,
mintot, meantot, sdtot, mediantot, maxtot);
#undef CONF_FMT_STRING
#define SANE(what,mean,median,sd) \
{ \
double d = (double)mean - median; \
if (d < 0) d = -d; \
if (d > 2 * sd ) \
printf("ERROR: The median and mean for " what " are more than twice the standard\n" \
" deviation apart. These results are NOT reliable.\n"); \
else if (d > sd ) \
printf("WARNING: The median and mean for " what " are not within a normal deviation\n" \
" These results are probably not that reliable.\n"); \
}
SANE("the initial connection time", meancon, mediancon, sdcon);
SANE("the processing time", meand, mediand, sdd);
SANE("the waiting time", meanwait, medianwait, sdwait);
SANE("the total time", meantot, mediantot, sdtot);
}
else {
printf(" min avg max\n");
#define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %5" APR_TIME_T_FMT "%5" APR_TIME_T_FMT "\n"
printf("Connect: " CONF_FMT_STRING, mincon, meancon, maxcon);
printf("Processing: " CONF_FMT_STRING, mind, meand, maxd);
printf("Waiting: " CONF_FMT_STRING, minwait, meanwait, maxwait);
printf("Total: " CONF_FMT_STRING, mintot, meantot, maxtot);
#undef CONF_FMT_STRING
}
/* Sorted on total connect times */
if (percentile && (done > 1)) {
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
if (g_us_granularity)
printf("\nPercentage of the requests served within a certain time (us)\n");
else
#endif // _WAF_BENCH_ // microsec-granularity in output-results
printf("\nPercentage of the requests served within a certain time (ms)\n");
for (i = 0; i < sizeof(percs) / sizeof(int); i++) {
if (percs[i] <= 0)
printf(" 0%% <0> (never)\n");
else if (percs[i] >= 100)
printf(" 100%% %5" APR_TIME_T_FMT " (longest request)\n",
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[done - 1].time:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[done - 1].time));
else
printf(" %d%% %5" APR_TIME_T_FMT "\n", percs[i],
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[(unsigned long)done * percs[i] / 100].time:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[(unsigned long)done * percs[i] / 100].time));
}
}
if (csvperc) {
FILE *out = fopen(csvperc, "w");
if (!out) {
perror("Cannot open CSV output file");
exit(1);
}
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
if (g_us_granularity)
fprintf(out, "" "Percentage served" "," "Time in us" "\n");
else
#endif // _WAF_BENCH_ // microsec-granularity in output-results
fprintf(out, "" "Percentage served" "," "Time in ms" "\n");
for (i = 0; i <= 100; i++) {
double t;
if (i == 0)
t = ap_double_ms(stats[0].time);
else if (i == 100)
t = ap_double_ms(stats[done - 1].time);
else
t = ap_double_ms(stats[(unsigned long) (0.5 + (double)done * i / 100.0)].time);
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
if (g_us_granularity)
t = t * 1000; // convert back to us
#endif // _WAF_BENCH_ // microsec-granularity in output-results
fprintf(out, "%d,%.3f\n", i, t);
}
fclose(out);
}
if (gnuplot) {
FILE *out = fopen(gnuplot, "w");
char tmstring[APR_CTIME_LEN];
if (!out) {
perror("Cannot open gnuplot output file");
exit(1);
}
fprintf(out, "starttime\tseconds\tctime\tdtime\tttime\twait\n");
for (i = 0; i < done; i++) {
(void) apr_ctime(tmstring, stats[i].starttime);
fprintf(out, "%s\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT
"\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT
"\t%" APR_TIME_T_FMT "\n", tmstring,
apr_time_sec(stats[i].starttime),
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[i].ctime:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[i].ctime),
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[i].time - stats[i].ctime:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[i].time - stats[i].ctime),
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[i].time:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[i].time),
#ifdef _WAF_BENCH_ // microsec-granularity in output-results
g_us_granularity?stats[i].waittime:
#endif // _WAF_BENCH_ // microsec-granularity in output-results
ap_round_ms(stats[i].waittime));
}
fclose(out);
}
}
if (sig) {
exit(1);
}
}