1 /****************************************************************************
2 * *
3 * The contents of this file are subject to the WebStone Public License *
4 * Version 1.0 (the "License"); you may not use this file except in *
5 * compliance with the License. You may obtain a copy of the License *
6 * at http://www.mindcraft.com/webstone/license10.html *
7 * *
8 * Software distributed under the License is distributed on an "AS IS" *
9 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See *
10 * the License for the specific language governing rights and limitations *
11 * under the License. *
12 * *
13 * The Original Code is WebStone 2.5. *
14 * *
15 * The Initial Developer of the Original Code is Silicon Graphics, Inc. *
16 * and Mindcraft, Inc.. Portions created by Silicon Graphics. and *
17 * Mindcraft. are Copyright (C) 1995-1998 Silicon Graphics, Inc. and *
18 * Mindcraft, Inc. All Rights Reserved. *
19 * *
20 * Contributor(s): ______________________________________. *
21 * *
22 * @(#) bench.c 2.4@(#) *
23 ***************************************************************************/
24
25 #include <stdio.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <math.h>
31 #include <limits.h>
32 #include <float.h>
33
34 #ifndef WIN32
35 #include <unistd.h>
36 #include <sys/time.h>
37 #include <sys/uio.h>
38 #include <sys/param.h>
39 #include <netdb.h>
40 #else
41 #include <windows.h>
42 #include <winsock.h>
43 #endif /* WIN32 */
44
45 #include "sysdep.h"
46 #include "bench.h"
47
48
49 /* allocate memory and exit if out of memory */
50 void *
mymalloc(size_t size)51 mymalloc(size_t size)
52 {
53 void *ptr;
54
55 ptr = malloc(size);
56 if (ptr == NULL)
57 errexit("Call to malloc() failed\n");
58 return ptr;
59 }
60
61
62 /*
63 * Receive n bytes from a socket
64 * Returns 0 on success, less than 0 on error.
65 */
66 int
recvdata(SOCKET sock,char * ptr,int nbytes)67 recvdata(SOCKET sock, char *ptr, int nbytes)
68 {
69 int nleft, nread, rv;
70 fd_set sockfds;
71 struct timeval timeout;
72
73 D_PRINTF("recvdata(): attempting to read %d bytes from socket %d, ptr %x\n", nbytes, sock, (int) ptr);
74 timeout.tv_sec = MAX_ACCEPT_SECS;
75 timeout.tv_usec = 0;
76 FD_ZERO(&sockfds);
77 FD_SET(sock, &sockfds);
78
79 /* Time out if the webmaster is too late with our GO
80 * by MAX_ACCEPT_SECS
81 */
82 if ((rv = select(FD_SETSIZE, &sockfds, NULL, NULL, &timeout)) == 0)
83 {
84 fprintf(stdout,
85 "Timeout waiting to write data after %d seconds\n",
86 MAX_ACCEPT_SECS);
87 D_PRINTF("select() timed out after %d seconds\n", MAX_ACCEPT_SECS);
88 errexit("Webclient terminating\n");
89 }
90
91 CLEAR_SOCK_ERR;
92 nleft = nbytes;
93 while (nleft > 0)
94 {
95 nread = NETREAD(sock, ptr, nleft);
96 if (SOCK_ERR(nread) || nread == 0)
97 {
98 fprintf(stderr, "Error in recvdata(): %s\n", neterrstr());
99 fprintf(stderr, "NETREAD() data: \"%.*s\"\n", nread, ptr);
100 D_PRINTF( "Error in recvdata(): %s\n", neterrstr());
101 return -1;
102 }
103
104 D_PRINTF( "NETREAD() data: %d bytes,\"%s\"\n", nread, ptr);
105 nleft -= nread;
106 ptr += nread;
107 }
108
109 /*
110 * if we somehow read too much then this return value will be
111 * less than zero, signifying an error.
112 */
113 return (nbytes - nleft);
114 }
115
116
117 /*
118 * Send n bytes to a socket
119 * Returns 0 on success, less than 0 on error.
120 */
121 int
senddata(SOCKET sock,char * ptr,int nbytes)122 senddata(SOCKET sock, char *ptr, int nbytes)
123 {
124 int nleft, nwritten;
125
126 TRACE("senddata(): entering, nbytes=%d.\n", nbytes);
127 CLEAR_SOCK_ERR;
128 nleft = nbytes;
129 while (nleft > 0)
130 {
131 nwritten = NETWRITE(sock, ptr, nleft);
132 if (SOCK_ERR(nwritten))
133 {
134 TRACE( "senddata(): returning error: %s\n", neterrstr() );
135 return -1;
136 }
137 nleft -= nwritten;
138 ptr += nwritten;
139 }
140 /*
141 * if we somehow wrote too much then this return value will be
142 * less than zero, signifying an error.
143 */
144 TRACE("senddata(): returning %d.\n", nbytes - nleft);
145 return (nbytes - nleft);
146 }
147
148 /* GENERAL NOTE: the conversion routines that follow pass their results
149 * back in a static arrays. A second call to the same routine overwrites
150 * the previous buffer value for that routine. If you want to save the
151 * value in the buffer copy it to another variable.
152 */
153 char *
timeval_to_text(const struct timeval * the_timeval)154 timeval_to_text(const struct timeval *the_timeval)
155 {
156 /*
157 * given a timeval (seconds and microseconds), put the text
158 * "seconds.microseconds" into timeval_as_text
159 * Note that the %10 printf() specifier is a MINIMUM field width.
160 */
161 THREAD static char timeval_as_text[SIZEOF_TIMEVALTEXT+1];
162 int seconds, microseconds;
163
164 seconds = the_timeval->tv_sec;
165 microseconds = the_timeval->tv_usec;
166 sprintf(timeval_as_text, "%10d.%6.6d\t", seconds, microseconds);
167 D_PRINTF("timeval_to_text(): returning '%s'\n", timeval_as_text);
168 return timeval_as_text;
169 }
170
171
172 char *
double_to_text(const double the_double)173 double_to_text(const double the_double)
174 {
175 /*
176 * given a double, return text
177 * Note that the %17 printf() specifier is a MINIMUM field width.
178 */
179 THREAD static char double_as_text[SIZEOF_DOUBLETEXT + 1];
180
181 sprintf(double_as_text, "%17.01f\t", the_double);
182 D_PRINTF("double_to_text(): returning '%s'\n", double_as_text);
183 return(double_as_text);
184 }
185
186 struct timeval
text_to_timeval(char * timeval_as_text)187 text_to_timeval(char *timeval_as_text)
188 {
189 long int seconds, microseconds;
190 struct timeval the_timeval;
191
192 D_PRINTF("T/%d %s\n", (int)timeval_as_text, timeval_as_text);
193 sscanf(timeval_as_text, "%ld.%ld", &seconds, µseconds);
194 the_timeval.tv_sec = seconds;
195 the_timeval.tv_usec = microseconds;
196 return the_timeval;
197 }
198
199 double
text_to_double(char * double_as_text)200 text_to_double(char *double_as_text)
201 {
202 double the_double = 0;
203
204 D_PRINTF("D/%d %s\n", (int)double_as_text, double_as_text);
205 sscanf(double_as_text, "%lf", &the_double);
206 return(the_double);
207 }
208
209
210 rqst_stats_t *
text_to_rqst_stats(char * rqst_stats_as_text)211 text_to_rqst_stats(char *rqst_stats_as_text)
212 {
213 THREAD static rqst_stats_t rqst_stats;
214 rqst_stats_t *the_rqst_stats = &rqst_stats;
215
216 the_rqst_stats->totalresponsetime =
217 text_to_timeval(strtok(rqst_stats_as_text, "\t"));
218
219 the_rqst_stats->totalresponsetimesq =
220 text_to_double(strtok((char *)NULL, "\t"));
221
222 the_rqst_stats->minresponsetime =
223 text_to_timeval(strtok((char *)NULL, "\t"));
224
225 the_rqst_stats->maxresponsetime =
226 text_to_timeval(strtok((char *)NULL, "\t"));
227
228 the_rqst_stats->totalconnecttime =
229 text_to_timeval(strtok((char *)NULL, "\t"));
230
231 the_rqst_stats->totalconnecttimesq =
232 text_to_double(strtok((char *)NULL, "\t"));
233
234 the_rqst_stats->minconnecttime =
235 text_to_timeval(strtok((char *)NULL, "\t"));
236
237 the_rqst_stats->maxconnecttime =
238 text_to_timeval(strtok((char *)NULL, "\t"));
239
240 the_rqst_stats->totalconnects = (unsigned long)
241 text_to_double(strtok((char *)NULL, "\t"));
242
243 the_rqst_stats->totalerrs = (unsigned long)
244 text_to_double(strtok((char *)NULL, "\t"));
245
246 the_rqst_stats->totalerrortime =
247 text_to_timeval(strtok((char *)NULL, "\t"));
248
249 the_rqst_stats->totalbytes =
250 text_to_double(strtok((char *)NULL, "\t"));
251
252 the_rqst_stats->totalbytessq =
253 text_to_double(strtok((char *)NULL, "\t"));
254
255 the_rqst_stats->minbytes =
256 text_to_double(strtok((char *)NULL, "\t"));
257
258 the_rqst_stats->maxbytes =
259 text_to_double(strtok((char *)NULL, "\t"));
260
261 the_rqst_stats->totalbody =
262 text_to_double(strtok((char *)NULL, "\t"));
263
264 the_rqst_stats->totalbodysq =
265 text_to_double(strtok((char *)NULL, "\t"));
266
267 the_rqst_stats->minbody =
268 text_to_double(strtok((char *)NULL, "\t"));
269
270 the_rqst_stats->maxbody =
271 text_to_double(strtok((char *)NULL, "\t"));
272
273 return(the_rqst_stats);
274 }
275
276
277 char *
rqst_stats_to_text(rqst_stats_t * the_rqst_stats)278 rqst_stats_to_text(rqst_stats_t *the_rqst_stats)
279 {
280 THREAD static char rqst_stats_as_text[SIZEOF_RQSTSTATSTEXT];
281 char *tmpbuf;
282
283 *rqst_stats_as_text = 0;
284
285 tmpbuf = timeval_to_text(&(the_rqst_stats->totalresponsetime));
286 strcat(rqst_stats_as_text, tmpbuf);
287
288 tmpbuf = double_to_text((the_rqst_stats->totalresponsetimesq));
289 strcat(rqst_stats_as_text, tmpbuf);
290
291 tmpbuf = timeval_to_text(&(the_rqst_stats->minresponsetime));
292 strcat(rqst_stats_as_text, tmpbuf);
293
294 tmpbuf = timeval_to_text(&(the_rqst_stats->maxresponsetime));
295 strcat(rqst_stats_as_text, tmpbuf);
296
297 tmpbuf = timeval_to_text(&(the_rqst_stats->totalconnecttime));
298 strcat(rqst_stats_as_text, tmpbuf);
299
300 tmpbuf = double_to_text((the_rqst_stats->totalconnecttimesq));
301 strcat(rqst_stats_as_text, tmpbuf);
302
303 tmpbuf = timeval_to_text(&(the_rqst_stats->minconnecttime));
304 strcat(rqst_stats_as_text, tmpbuf);
305
306 tmpbuf = timeval_to_text(&(the_rqst_stats->maxconnecttime));
307 strcat(rqst_stats_as_text, tmpbuf);
308
309 tmpbuf = double_to_text((the_rqst_stats->totalconnects));
310 strcat(rqst_stats_as_text, tmpbuf);
311
312 tmpbuf = double_to_text((the_rqst_stats->totalerrs));
313 strcat(rqst_stats_as_text, tmpbuf);
314
315 tmpbuf = timeval_to_text(&(the_rqst_stats->totalerrortime));
316 strcat(rqst_stats_as_text, tmpbuf);
317
318 tmpbuf = double_to_text((the_rqst_stats->totalbytes));
319 strcat(rqst_stats_as_text, tmpbuf);
320
321 tmpbuf = double_to_text((the_rqst_stats->totalbytessq));
322 strcat(rqst_stats_as_text, tmpbuf);
323
324 tmpbuf = double_to_text((the_rqst_stats->minbytes));
325 strcat(rqst_stats_as_text, tmpbuf);
326
327 tmpbuf = double_to_text((the_rqst_stats->maxbytes));
328 strcat(rqst_stats_as_text, tmpbuf);
329
330 tmpbuf = double_to_text((the_rqst_stats->totalbody));
331 strcat(rqst_stats_as_text, tmpbuf);
332
333 tmpbuf = double_to_text((the_rqst_stats->totalbodysq));
334 strcat(rqst_stats_as_text, tmpbuf);
335
336 tmpbuf = double_to_text((the_rqst_stats->minbody));
337 strcat(rqst_stats_as_text, tmpbuf);
338
339 tmpbuf = double_to_text((the_rqst_stats->maxbody));
340 strcat(rqst_stats_as_text, tmpbuf);
341
342 D_PRINTF( "rqst_stats_to_text returning %d: %s\n",
343 strlen(rqst_stats_as_text), rqst_stats_as_text );
344
345 return(rqst_stats_as_text);
346 }
347
348
349 stats_t *
text_to_stats(char * stats_as_text)350 text_to_stats(char *stats_as_text)
351 {
352 int i;
353 rqst_stats_t *the_rqst_stats;
354 THREAD static stats_t stats;
355 stats_t *the_stats = &stats;
356
357 D_PRINTF( "Parsing stats: %s\n", stats_as_text );
358 /* grab stats.rs */
359 the_rqst_stats = text_to_rqst_stats(stats_as_text);
360 the_stats->rs = *the_rqst_stats;
361
362 /* grab main structure */
363 the_stats->starttime = text_to_timeval(strtok((char *)NULL, "\t"));
364 the_stats->endtime = text_to_timeval(strtok((char *)NULL, "\t"));
365 the_stats->datatime = text_to_timeval(strtok((char *)NULL, "\t"));
366 the_stats->totalpages =
367 (unsigned long) text_to_double(strtok((char *)NULL, "\t"));
368 the_stats->total_num_of_files =
369 (unsigned int) text_to_double(strtok((char *)NULL, "\t"));
370 for (i = 0; i < number_of_pages; i++)
371 {
372 the_stats->page_numbers[i] =
373 (unsigned int) text_to_double(strtok((char *)NULL, "\t"));
374 }
375 /* return bytes read */
376 D_PRINTF( "Returning stats\n");
377 return(the_stats);
378 }
379
380
381 char *
stats_to_text(const stats_t * the_stats)382 stats_to_text(const stats_t *the_stats)
383 {
384 int i;
385 THREAD static char stats_as_text[SIZEOF_STATSTEXT];
386 char *tmpbuf;
387 rqst_stats_t the_rqst_stats;
388
389 TRACE("stats_to_text(): entering.\n");
390 *stats_as_text = 0;
391
392 /* stats.rs */
393 the_rqst_stats = the_stats->rs;
394 tmpbuf = rqst_stats_to_text(&the_rqst_stats);
395 strcat(stats_as_text, tmpbuf);
396
397 /* main structure */
398 tmpbuf = timeval_to_text(&(the_stats->starttime));
399 strcat(stats_as_text, tmpbuf);
400
401 tmpbuf = timeval_to_text(&(the_stats->endtime));
402 strcat(stats_as_text, tmpbuf);
403
404 tmpbuf = timeval_to_text(&(the_stats->datatime));
405 strcat(stats_as_text, tmpbuf);
406
407 tmpbuf = double_to_text((the_stats->totalpages));
408 strcat(stats_as_text, tmpbuf);
409
410 tmpbuf = double_to_text((the_stats->total_num_of_files));
411 strcat(stats_as_text, tmpbuf);
412
413 for (i = 0; i < number_of_pages; i++)
414 {
415 tmpbuf = double_to_text((the_stats->page_numbers[i]));
416 strcat(stats_as_text, tmpbuf);
417 }
418
419 strcat(stats_as_text, "\n");
420
421 TRACE("stats_as_text(): leaving.\n");
422 return stats_as_text;
423 }
424
425
426 page_stats_t *
text_to_page_stats(char * page_stats_as_text)427 text_to_page_stats(char *page_stats_as_text)
428 {
429 rqst_stats_t *the_rqst_stats;
430 THREAD static page_stats_t pagestat;
431 page_stats_t *pagestats = &pagestat;
432
433 /* grab stats.rs */
434 the_rqst_stats = text_to_rqst_stats(page_stats_as_text);
435
436 /* grab main structure */
437 pagestats->totalpages =
438 (unsigned long) text_to_double(strtok((char *)NULL, "\t"));
439
440 pagestats->page_size =
441 (unsigned int) text_to_double(strtok((char *)NULL, "\t"));
442
443 pagestats->page_valid = (int) text_to_double(strtok((char *)NULL, "\t"));
444
445 pagestats->rs = *the_rqst_stats;
446
447 return(pagestats);
448 }
449
450
451 char *
page_stats_to_text(const page_stats_t * pagestats)452 page_stats_to_text(const page_stats_t *pagestats)
453 {
454 THREAD static char page_stats_as_text[SIZEOF_PAGESTATSTEXT];
455 char *tmpbuf;
456 rqst_stats_t the_rqst_stats;
457
458 TRACE("page_stats_to_text(): entering.\n");
459 *page_stats_as_text = 0;
460
461 /* stats.rs */
462 the_rqst_stats = pagestats->rs;
463 tmpbuf = rqst_stats_to_text(&the_rqst_stats);
464 strcat(page_stats_as_text, tmpbuf);
465
466 /* main structure */
467 tmpbuf = double_to_text(pagestats->totalpages);
468 strcat(page_stats_as_text, tmpbuf);
469
470 tmpbuf = double_to_text(pagestats->page_size);
471 strcat(page_stats_as_text, tmpbuf);
472
473 tmpbuf = double_to_text(pagestats->page_valid);
474 strcat(page_stats_as_text, tmpbuf);
475
476 strcat(page_stats_as_text, "\n");
477
478 TRACE("page_stats_to_text(): exiting.\n");
479 return(page_stats_as_text);
480 }
481
482 void
rqtimer_init(rqst_timer_t * p)483 rqtimer_init(rqst_timer_t *p)
484 {
485 memset(p, 0, sizeof(*p));
486 }
487
488 void
rqstat_init(rqst_stats_t * p)489 rqstat_init(rqst_stats_t *p)
490 {
491 memset(p, 0, sizeof(*p));
492
493 p->minbytes = DBL_MAX;
494 p->minbody = DBL_MAX;
495 p->minconnecttime.tv_sec = LONG_MAX;
496 p->minconnecttime.tv_usec = LONG_MAX;
497 p->minresponsetime.tv_sec = LONG_MAX;
498 p->minresponsetime.tv_usec = LONG_MAX;
499 }
500
501
502 void
stats_init(stats_t * p)503 stats_init(stats_t *p)
504 {
505 memset(p, 0, sizeof(*p));
506
507 p->rs.minbytes = DBL_MAX;
508 p->rs.minbody = DBL_MAX;
509 p->rs.minconnecttime.tv_sec = LONG_MAX;
510 p->rs.minconnecttime.tv_usec = LONG_MAX;
511 p->rs.minresponsetime.tv_sec = LONG_MAX;
512 p->rs.minresponsetime.tv_usec = LONG_MAX;
513 }
514
515
516 void
page_stats_init(page_stats_t * p)517 page_stats_init(page_stats_t *p)
518 {
519 memset(p, 0, sizeof(*p));
520
521 p->rs.minbytes = DBL_MAX;
522 p->rs.minbody = DBL_MAX;
523 p->rs.minconnecttime.tv_sec = LONG_MAX;
524 p->rs.minconnecttime.tv_usec = LONG_MAX;
525 p->rs.minresponsetime.tv_sec = LONG_MAX;
526 p->rs.minresponsetime.tv_usec = LONG_MAX;
527 }
528
529
530 void
rqstat_times(rqst_stats_t * rs,rqst_timer_t * rt)531 rqstat_times(rqst_stats_t *rs, rqst_timer_t *rt)
532 {
533 double t;
534
535 /* calculate in milliseconds to avoid underflow */
536
537 compdifftime(&(rt->exittime), &(rt->entertime), &(rs->totalresponsetime));
538 t = 1000 * timevaldouble(&(rs->totalresponsetime));
539 rs->totalresponsetimesq = t * t;
540 doubletimeval(t, &(rs->totalresponsetime));
541
542 rs->minresponsetime = rs->totalresponsetime;
543 rs->maxresponsetime = rs->totalresponsetime;
544
545 compdifftime(&(rt->afterconnect), &(rt->beforeconnect),
546 &(rs->totalconnecttime));
547 t = 1000 * timevaldouble(&(rs->totalconnecttime));
548 rs->totalconnecttimesq = t * t;
549 doubletimeval(t, &(rs->totalconnecttime));
550
551 rs->minconnecttime = rs->totalconnecttime;
552 rs->maxconnecttime = rs->totalconnecttime;
553
554 rs->totalbody = rt->bodybytes;
555 rs->totalbodysq = ((double)(rt->bodybytes)) * ((double)(rt->bodybytes));
556 rs->minbody = rt->bodybytes;
557 rs->maxbody = rt->bodybytes;
558
559 rs->totalbytes = rt->totalbytes;
560 rs->totalbytessq = ((double)(rt->totalbytes)) * ((double)(rt->totalbytes));
561 rs->minbytes = rt->totalbytes;
562 rs->maxbytes = rt->totalbytes;
563
564 rs->totalconnects = 1;
565 rs->totalerrs = 0;
566 rs->totalerrortime.tv_sec = 0;
567 rs->totalerrortime.tv_usec = 0;
568 }
569
570 void
rqstat_sum(rqst_stats_t * sum,rqst_stats_t * incr)571 rqstat_sum(rqst_stats_t *sum, rqst_stats_t *incr)
572 {
573 addtime( &(sum->totalresponsetime), &(incr->totalresponsetime));
574 mintime( &(sum->minresponsetime), &(incr->minresponsetime));
575 maxtime( &(sum->maxresponsetime), &(incr->maxresponsetime));
576 sum->totalresponsetimesq += incr->totalresponsetimesq;
577
578 addtime( &(sum->totalconnecttime), &(incr->totalconnecttime));
579 mintime( &(sum->minconnecttime), &(incr->minconnecttime));
580 maxtime( &(sum->maxconnecttime), &(incr->maxconnecttime));
581 sum->totalconnecttimesq += incr->totalconnecttimesq;
582
583 sum->totalconnects += incr->totalconnects;
584 sum->totalerrs += incr->totalerrs;
585 addtime( &(sum->totalerrortime), &(incr->totalerrortime));
586
587 sum->totalbytes += incr->totalbytes;
588
589 sum->totalbytessq += incr->totalbytessq;
590 sum->minbytes = min(sum->minbytes, incr->minbytes);
591 sum->maxbytes = max(sum->maxbytes, incr->maxbytes);
592
593 sum->totalbody += incr->totalbody;
594
595 sum->totalbodysq += incr->totalbodysq;
596 sum->minbody = min(sum->minbody, incr->minbody);
597 sum->maxbody = max(sum->maxbody, incr->maxbody);
598 }
599
600
601 void
rqstat_print(rqst_stats_t * stats)602 rqstat_print(rqst_stats_t *stats)
603 {
604 rqstat_fprint(stdout, stats);
605 }
606
607
608 void
rqstat_fprint(FILE * f,rqst_stats_t * stats)609 rqstat_fprint(FILE *f, rqst_stats_t *stats)
610 {
611 struct timeval meantime, /*vartime,*/ stdtime;
612
613 fprintf(f, "%d connection(s) to server, %d errors\n",
614 stats->totalconnects, stats->totalerrs);
615
616 if (stats->totalconnects == 0) {
617 fprintf(f,"NO CONNECTIONS, THEREFORE NO STATISTICS\n"
618 "IS YOUR WEBSERVER RUNNING?\n"
619 "DO THE PAGES EXIST ON THE SERVER?\n");
620 return;
621 }
622
623 /* title */
624 fprintf(f, "\n Average Std Dev Minimum Maximum\n\n");
625
626 /* first line (connect time) */
627 avgtime(&(stats->totalconnecttime),
628 stats->totalconnects, &meantime);
629
630 /* variancetime(&(stats->totalconnecttime),
631 stats->totalconnecttimesq,
632 stats->totalconnects, &vartime); */
633
634 stddevtime(&(stats->totalconnecttime),
635 stats->totalconnecttimesq,
636 stats->totalconnects, &stdtime);
637
638 /* convert from milliseconds to seconds - see rqstat_times() */
639 fprintf(f, "Connect time (sec) %10.6lf %10.6lf %10.6lf %10.6lf\n",
640 timevaldouble(&meantime) / 1000, timevaldouble(&stdtime) / 1000,
641 timevaldouble(&(stats->minconnecttime)) / 1000,
642 timevaldouble(&(stats->maxconnecttime)) / 1000);
643
644 TRACE("total connect time: %lf sum of squares: %lf count: %d\n",
645 timevaldouble(&(stats->totalconnecttime)),
646 stats->totalconnecttimesq,
647 stats->totalconnects);
648
649 /* second line (response time) */
650 avgtime(&(stats->totalresponsetime), stats->totalconnects, &meantime);
651
652 /* variancetime(&(stats->totalresponsetime), stats->totalresponsetimesq,
653 stats->totalconnects, &vartime); */
654
655 stddevtime(&(stats->totalresponsetime), stats->totalresponsetimesq,
656 stats->totalconnects, &stdtime);
657
658 /* convert from milliseconds to seconds - see rqstat_times() */
659 fprintf(f,
660 "Response time (sec) %10.6lf %10.6lf %10.6lf %10.6lf\n",
661 timevaldouble(&meantime) / 1000, timevaldouble(&stdtime) / 1000,
662 timevaldouble(&(stats->minresponsetime)) / 1000,
663 timevaldouble(&(stats->maxresponsetime)) / 1000);
664
665 TRACE("total response time: %lf sum of squares: %lf count: %d\n",
666 timevaldouble(&(stats->totalresponsetime)),
667 stats->totalresponsetimesq,
668 stats->totalconnects);
669
670 /* 3rd-5th lines (response size, body size, # bytes moved */
671 fprintf(f,
672 "Response size (bytes) %10.0lf %10.0lf %10.0lf %10.0lf\n",
673 mean(stats->totalbytes, stats->totalconnects),
674 stddev(stats->totalbytes, stats->totalbytessq,
675 stats->totalconnects),
676 stats->minbytes,
677 stats->maxbytes);
678
679 fprintf(f, "Body size (bytes) %10.0lf %10.0lf %10.0lf %10.0lf\n\n",
680 mean(stats->totalbody, stats->totalconnects),
681 stddev(stats->totalbody, stats->totalbodysq, stats->totalconnects),
682 stats->minbody,
683 stats->maxbody);
684
685 fprintf(f,
686 "%.0lf body bytes moved + %.0lf header bytes moved = %.0lf total\n",
687 stats->totalbody,
688 stats->totalbytes - stats->totalbody,
689 stats->totalbytes);
690 }
691