Here are some cleanups to get ab working a bit nicer with APR (based on
what I know). ab is currently broken on Solaris/Sparc. I tested it on
Solaris/Sparc and FreeBSD/Intel. (Both of these platforms have %lld and
LLONG_MAX - are there some that don't? If not, we need to do something with
APR's configure a la APR_OFF_T_FMT. Win32 has APR_TIME_T_FMT, but Unix
doesn't...)
The format of the min, mean, sd, median, and max output could be cleaned
up further. I also bumped up the precision of the Time per request field
to three decimal places - when I tested it against static pages, I kept
getting 0.00. =-)
Suggestions or comments? -- justin
Index: support/ab.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/support/ab.c,v
retrieving revision 1.69
diff -u -r1.69 ab.c
--- support/ab.c 2001/04/03 16:49:25 1.69
+++ support/ab.c 2001/04/11 03:19:49
@@ -226,13 +226,13 @@
#ifdef USE_SSL
/* XXXX insert SSL timings */
#endif
- int read; /* number of bytes read */
- long starttime; /* start time of connection in seconds since
- * Jan. 1, 1970 */
- long waittime; /* Between writing request and reading
- * response */
- long ctime; /* time in ms to connect */
- long time; /* time in ms for connection */
+ int read; /* number of bytes read */
+ apr_time_t starttime; /* start time of connection in seconds since
+ * Jan. 1, 1970 */
+ apr_time_t waittime; /* Between writing request and reading
+ * response */
+ apr_time_t ctime; /* time in ms to connect */
+ apr_time_t time; /* time in ms for connection */
};
#define ap_min(a,b) ((a)<(b))?(a):(b)
@@ -430,8 +430,8 @@
static int compri(struct data * a, struct data * b)
{
- int p = a->time - a->ctime;
- int q = b->time - b->ctime;
+ apr_time_t p = a->time - a->ctime;
+ apr_time_t q = b->time - b->ctime;
if (p < q)
return -1;
if (p > q)
@@ -450,11 +450,15 @@
static void output_results(void)
{
- long timetaken;
+ apr_off_t timetakenusec, secondstaken, millisecondstaken;
+ float timetaken;
endtime = apr_time_now();
- timetaken = (endtime - start) / 1000;
-
+ timetakenusec = endtime - start;
+ timetaken = (float) timetakenusec / APR_USEC_PER_SEC;
+ secondstaken = (apr_off_t) timetakenusec / APR_USEC_PER_SEC;
+ millisecondstaken = (apr_off_t) timetakenusec % APR_USEC_PER_SEC;
+
printf("\r
\r");
printf("Server Software: %s\n", servername);
printf("Server Hostname: %s\n", hostname);
@@ -464,8 +468,8 @@
printf("Document Length: %d bytes\n", doclen);
printf("\n");
printf("Concurrency Level: %d\n", concurrency);
- printf("Time taken for tests: %qd.%03qd seconds\n",
- timetaken / APR_USEC_PER_SEC, timetaken % APR_USEC_PER_SEC);
+ printf("Time taken for tests: %" APR_OFF_T_FMT ".%03" APR_OFF_T_FMT "
+seconds\n",
+ secondstaken, millisecondstaken);
printf("Complete requests: %ld\n", done);
printf("Failed requests: %ld\n", bad);
if (bad)
@@ -483,17 +487,17 @@
/* avoid divide by zero */
if (timetaken) {
- printf("Requests per second: %.2f [#/sec] (mean)\n", 1000 * (float) (done)
/ timetaken);
- printf("Time per request: %.2f [ms] (mean)\n", concurrency * timetaken /
(float) done);
- printf("Time per request: %.2f [ms] (mean, across all concurent
requests)\n",
- timetaken / (float) done);
+ printf("Requests per second: %.2f [#/sec] (mean)\n", done / timetaken);
+ printf("Time per request: %.3f [ms] (mean)\n", concurrency * timetaken /
+done);
+ printf("Time per request: %.3f [ms] (mean, across all concurent
+requests)\n",
+ timetaken / done);
printf("Transfer rate: %.2f [Kbytes/sec] received\n",
- (float) (totalread) / timetaken);
+ totalread / 1024 / timetaken);
if (posting > 0) {
printf(" %.2f kb/s sent\n",
- (float) (totalposted) / timetaken);
+ (float) totalposted / timetaken / 1024);
printf(" %.2f kb/s total\n",
- (float) (totalread + totalposted) / timetaken);
+ (float) (totalread + totalposted) / timetaken / 1024);
}
}
@@ -501,19 +505,20 @@
/* work out connection times */
long i;
double totalcon = 0, total = 0, totald = 0, totalwait = 0;
- long mincon = 9999999, mintot = 999999, mind = 99999, minwait = 99999;
- long maxcon = 0, maxtot = 0, maxd = 0, maxwait = 0;
- long meancon = 0, meantot = 0, meand = 0, meanwait = 0;
- double sdtot = 0, sdcon = 0, sdd = 0, sdwait = 0;
+ apr_time_t mincon, mintot, mind, minwait;
+ apr_time_t maxcon = 0, maxtot = 0, maxd = 0, maxwait = 0;
+ apr_time_t meancon = 0, meantot = 0, meand = 0, meanwait = 0;
+ double sdtot = 0, sdcon = 0, sdd = 0, sdwait = 0;
+
+ mincon = mintot = mind = minwait = LLONG_MAX;
for (i = 0; i < requests; i++) {
struct data s = stats[i];
mincon = ap_min(mincon, s.ctime);
mintot = ap_min(mintot, s.time);
- mind = ap_min(mintot, s.time - s.ctime);
+ mind = ap_min(mind, s.time - s.ctime);
minwait = ap_min(minwait, s.waittime);
- maxtot = ap_max(maxtot, s.time);
maxcon = ap_max(maxcon, s.ctime);
maxtot = ap_max(maxtot, s.time);
maxd = ap_max(maxd, s.time - s.ctime);
@@ -531,7 +536,7 @@
for (i = 0; i < requests; i++) {
struct data s = stats[i];
- int a;
+ apr_off_t a;
a = (s.time - total);
sdtot += a * a;
a = (s.ctime - totalcon);
@@ -550,7 +555,7 @@
if (gnuplot) {
FILE *out = fopen(gnuplot, "w");
long i;
- long sttime;
+ apr_time_t sttime;
char tmstring[1024];/* XXXX */
if (!out) {
perror("Cannot open gnuplot output file");
@@ -563,7 +568,7 @@
tmstring[strlen(tmstring) - 1] = '\0'; /* ctime returns a
* string with a
* trailing newline */
- fprintf(out, "%s\t%ld\t%ld\t%ld\t%ld\t%ld\n",
+ fprintf(out, "%s\t%lld\t%lld\t%lld\t%lld\t%lld\n",
tmstring,
sttime,
stats[i].ctime,
@@ -573,11 +578,11 @@
}
fclose(out);
};
- /*
- * XXX: what is better; this hideous cast of the copare function; or
- * the four warnings during compile ? dirkx just does not know and
- * hates both/
- */
+ /*
+ * XXX: what is better; this hideous cast of the copare function; or
+ * the four warnings during compile ? dirkx just does not know and
+ * hates both/
+ */
qsort(stats, requests, sizeof(struct data),
(int (*) (const void *, const void *)) compradre);
if ((requests > 1) && (requests % 2))
@@ -606,20 +611,21 @@
meantot = (stats[requests / 2].time + stats[requests / 2 + 1].time) / 2;
else
meantot = stats[requests / 2].time;
-
- printf("\nConnnection Times (ms)\n");
+ printf("\nConnection Times (ms)\n");
if (confidence) {
- printf(" min mean[+/-sd] median max\n");
- printf("Connect: %5ld %5d %6.1f %5ld %5ld\n",
- mincon, (int) (totalcon + 0.5), sdcon, meancon, maxcon);
- printf("Processing: %5ld %5d %6.1f %5ld %5ld\n",
+#define CONF_FMT_STRING "%lld %5d %6.1f %lld %lld\n"
+ printf(" min mean[+/-sd] median max\n");
+ printf("Connect: " CONF_FMT_STRING,
+ mincon, (int) (totalcon + 0.5), sdcon, meancon, maxcon);
+ printf("Processing: " CONF_FMT_STRING,
mind, (int) (totald + 0.5), sdd, meand, maxd);
- printf("Waiting: %5ld %5d %6.1f %5ld %5ld\n",
+ printf("Waiting: " CONF_FMT_STRING,
minwait, (int) (totalwait + 0.5), sdwait, meanwait, maxwait);
- printf("Total: %5ld %5d %6.1f %5ld %5ld\n",
+ printf("Total: " CONF_FMT_STRING,
mintot, (int) (total + 0.5), sdtot, meantot, maxtot);
+#undef CONF_FMT_STRING
#define SANE(what,avg,mean,sd) \
{ \
@@ -639,11 +645,13 @@
}
else {
printf(" min avg max\n");
- printf("Connect: %5ld %5e %5ld\n", mincon, totalcon / requests, maxcon);
- printf("Processing: %5ld %5e %5ld\n",
+ printf("Connect: %5lld %5e %5lld\n", mincon, totalcon / requests,
+ maxcon);
+ printf("Processing: %5lld %5e %5lld\n",
mintot - mincon, (total / requests) - (totalcon / requests),
maxtot - maxcon);
- printf("Total: %5ld %5e %5ld\n", mintot, total / requests, maxtot);
+ printf("Total: %5lld %5e %5lld\n", mintot, total / requests,
+ maxtot);
}
@@ -654,9 +662,10 @@
if (percs[i] <= 0)
printf(" 0%% <0> (never)\n");
else if (percs[i] >= 100)
- printf(" 100%% %5ld (last request)\n", stats[(int) (requests -
1)].time);
+ printf(" 100%% %5lld (longest request)\n",
+ stats[requests - 1].time);
else
- printf(" %d%% %5ld\n",
+ printf(" %d%% %5lld\n",
percs[i], stats[(int) (requests * percs[i] / 100)].time);
};
if (csvperc) {