* src/httperf.c: New functionality for variable periodic rates * src/httperf.h: ditto * src/timer.c: dittoahc_fix_select
@@ -1,6 +1,23 @@ | |||
Ted Bullock (compiler fixes, alloca include) | |||
Tai Jin (zero-length content fix) | |||
David Mosberger (main sources, wsesslog crash fix) | |||
Martin Arlitt (SSL support, timer reset fix) | |||
Stephane Eranian (wlog URI generator) | |||
Richard Carter (wsesslog workload generator) | |||
David Mosberger | |||
main sources | |||
wsesslog crash fix | |||
Martin Arlitt | |||
SSL support | |||
timer reset fix | |||
Ted Bullock | |||
compiler warning fixes | |||
gnu auto tool build system | |||
Tai Jin | |||
zero-length content fix | |||
Stephane Eranian | |||
wlog URI generator | |||
Richard Carter | |||
wsesslog workload generator | |||
Andrew Hately | |||
variable rates of period between sessions/requests |
@@ -1,3 +1,10 @@ | |||
2007-05-27 Andrew Hateley <andrew.hateley@gmail.com> | |||
* man/httperf.1: New documentation regarding the variable periodic rates | |||
* src/httperf.c: New functionality for variable periodic rates | |||
* src/httperf.h: ditto | |||
* src/timer.c: ditto | |||
2007-03-31 Ted Bullock <tbullock@canada.com> | |||
* *.c and *.h: Adjusted license to explicitly list HP copyright as | |||
@@ -42,6 +42,9 @@ | |||
#include <rate.h> | |||
#include <timer.h> | |||
int current_rate = 0; | |||
Time duration_in_current_rate = 0; | |||
/* By pushing the random number generator state into the caller via | |||
the xsubi array below, we gain some test repeatability. For | |||
example, let us say one generator was starting sessions, and a | |||
@@ -75,6 +78,24 @@ next_arrival_time_exp (Rate_Generator *rg) | |||
return -mean*log (1.0 - erand48 (rg->xsubi)); | |||
} | |||
static Time | |||
next_arrival_time_variable (Rate_Generator *rg) | |||
{ | |||
Time next; | |||
next = rg->rate->iat[current_rate]; | |||
duration_in_current_rate += next; | |||
if (duration_in_current_rate >= rg->rate->duration[current_rate]) | |||
{ | |||
current_rate++; | |||
if (current_rate >= rg->rate->numRates) | |||
current_rate = 0; | |||
duration_in_current_rate = 0; | |||
} | |||
return (next); | |||
} | |||
static void | |||
tick (Timer *t, Any_Type arg) | |||
{ | |||
@@ -133,6 +154,7 @@ rate_generator_start (Rate_Generator *rg, Event_Type completion_event) | |||
case DETERMINISTIC: func = next_arrival_time_det; break; | |||
case UNIFORM: func = next_arrival_time_uniform; break; | |||
case EXPONENTIAL: func = next_arrival_time_exp; break; | |||
case VARIABLE: func = next_arrival_time_variable; break; | |||
default: | |||
fprintf (stderr, "%s: unrecognized interarrival distribution %d\n", | |||
prog_name, rg->rate->dist); | |||
@@ -139,6 +139,7 @@ static struct option longopts[] = | |||
{"think-timeout",required_argument, (int *) ¶m.think_timeout, 0}, | |||
{"timeout", required_argument, (int *) ¶m.timeout, 0}, | |||
{"uri", required_argument, (int *) ¶m.uri, 0}, | |||
{"use-timer-cache", no_argument, ¶m.use_timer_cache, 1}, | |||
{"verbose", no_argument, 0, 'v'}, | |||
{"version", no_argument, 0, 'V'}, | |||
{"wlog", required_argument, (int *) ¶m.wlog, 0}, | |||
@@ -169,7 +170,9 @@ usage (void) | |||
"\t[--think-timeout X] [--timeout X] [--uri S] [--verbose] " | |||
"[--version]\n" | |||
"\t[--wlog y|n,file] [--wsess N,N,X] [--wsesslog N,X,file]\n" | |||
"\t[--wset N,X]\n", | |||
"\t[--wset N,X]\n" | |||
"\t[--period [v]T1,D1[,T2,D2]\n" | |||
"\t[--use-timer-cache]\n", | |||
prog_name); | |||
} | |||
@@ -230,6 +233,8 @@ main (int argc, char **argv) | |||
void *flag; | |||
Time t; | |||
int numRates = 0; | |||
#ifdef __FreeBSD__ | |||
/* This works around a bug in earlier versions of FreeBSD that cause | |||
non-finite IEEE arithmetic to cause SIGFPE instead of the | |||
@@ -409,6 +414,7 @@ main (int argc, char **argv) | |||
case 'd': param.rate.dist = DETERMINISTIC; break; | |||
case 'u': param.rate.dist = UNIFORM; break; | |||
case 'e': param.rate.dist = EXPONENTIAL; break; | |||
case 'v': param.rate.dist = VARIABLE; break; | |||
default: | |||
fprintf (stderr, "%s: illegal interarrival distribution " | |||
"'%c' in %s\n", | |||
@@ -461,6 +467,62 @@ main (int argc, char **argv) | |||
+ param.rate.max_iat); | |||
break; | |||
case VARIABLE: | |||
while(1) | |||
{ | |||
if (numRates >= NUM_RATES) | |||
{ | |||
fprintf (stderr, "%s: too many rates\n", | |||
prog_name); | |||
exit (1); | |||
} | |||
param.rate.iat[numRates] = strtod (optarg, &end); | |||
if (errno == ERANGE || end == optarg || | |||
param.rate.iat[numRates] < 0) | |||
{ | |||
fprintf (stderr, "%s: illegal minimum interarrival" | |||
" time %s\n", prog_name, optarg); | |||
exit (1); | |||
} | |||
if (*end != ',') | |||
{ | |||
fprintf (stderr, "%s: interarrival time not " | |||
"followed by `,duration' (rest: `%s')\n", | |||
prog_name, end); | |||
exit (1); | |||
} | |||
optarg = end + 1; | |||
param.rate.duration[numRates] = strtod (optarg, &end); | |||
if (errno == ERANGE || end == optarg || | |||
param.rate.duration[numRates] < 0) | |||
{ | |||
fprintf (stderr, "%s: illegal duration %s\n", | |||
prog_name, optarg); | |||
exit (1); | |||
} | |||
if (numRates == 0) | |||
param.rate.mean_iat = param.rate.iat[numRates]; | |||
else | |||
param.rate.mean_iat += param.rate.iat[numRates]; | |||
numRates++; | |||
if (*end != ',') | |||
{ | |||
param.rate.numRates = numRates; | |||
break; | |||
} | |||
else | |||
optarg = end + 1; | |||
} | |||
param.rate.mean_iat /= numRates; | |||
break; | |||
default: | |||
fprintf (stderr, "%s: internal error parsing %s\n", | |||
prog_name, optarg); | |||
@@ -893,6 +955,20 @@ main (int argc, char **argv) | |||
printf (" --period=e%g", param.rate.mean_iat); | |||
break; | |||
case VARIABLE: | |||
{ | |||
int m; | |||
printf (" --period=v"); | |||
for(m=0; m<param.rate.numRates; m++) | |||
{ | |||
if (m != 0) | |||
printf (","); | |||
printf ("%g,%g", param.rate.iat[m], | |||
param.rate.duration[m]); | |||
} | |||
} | |||
break; | |||
default: | |||
printf("--period=??"); | |||
break; | |||
@@ -911,6 +987,7 @@ main (int argc, char **argv) | |||
if (param.additional_header) | |||
printf (" --add-header='%s'", param.additional_header); | |||
if (param.method) printf (" --method=%s", param.method); | |||
if (param.use_timer_cache) printf (" --use-timer-cache"); | |||
if (param.wsesslog.num_sessions) | |||
{ | |||
/* This overrides any --wsess, --num-conns, --num-calls, | |||
@@ -46,6 +46,8 @@ typedef double Time; | |||
#define NELEMS(a) ((sizeof (a)) / sizeof ((a)[0])) | |||
#define TV_TO_SEC(tv) ((tv).tv_sec + 1e-6*(tv).tv_usec) | |||
#define NUM_RATES 16 | |||
typedef union | |||
{ | |||
char c; | |||
@@ -65,6 +67,7 @@ typedef enum Dist_Type | |||
{ | |||
DETERMINISTIC, /* also called fixed-rate */ | |||
UNIFORM, /* over interval [min_iat,max_iat) */ | |||
VARIABLE, /* allows varying input load */ | |||
EXPONENTIAL /* with mean mean_iat */ | |||
} | |||
Dist_Type; | |||
@@ -98,6 +101,9 @@ typedef struct Rate_Info | |||
Time mean_iat; /* mean interarrival time */ | |||
Time min_iat; /* min interarrival time (for UNIFORM) */ | |||
Time max_iat; /* max interarrival time (for UNIFORM) */ | |||
int numRates; /* number of rates we want to use */ | |||
Time iat[NUM_RATES]; | |||
Time duration[NUM_RATES]; | |||
} | |||
Rate_Info; | |||
@@ -134,6 +140,7 @@ typedef struct Cmdline_Params | |||
int ssl_reuse; /* reuse SSL Session ID */ | |||
const char *ssl_cipher_list; /* client's list of SSL cipher suites */ | |||
#endif | |||
int use_timer_cache; | |||
const char *additional_header; /* additional request header(s) */ | |||
const char *method; /* default call method */ | |||
struct | |||
@@ -75,7 +75,10 @@ timer_now_forced (void) | |||
Time | |||
timer_now (void) | |||
{ | |||
return now; | |||
if(param.use_timer_cache) | |||
return now; | |||
else | |||
return timer_now_forced (); | |||
} | |||
void | |||