Polygraph 2.5.2 does not adjust working set size for the number of client-server pairs in the setup, resulting in larger than needed WSS for request rates exceeding 400/sec. This patch does three things: - adds the "client_host_count" field to the Bench object (PGL) - adds the clientHostCount() function to compute the number of client hosts based on the PolyMix-3 rules (PGL) - sets TheBench.client_host_count to clientHostCount(TheBench) and uses TheBench.client_host_count to adjust WSS and other parameters that depend on the number of client-server pairs (polymix-3.pg and polymix-3-guts.pg) The patch modifies polymix-3*pg files. Please read the comments in updated polymix-3.pg carefully before setting workload parameters: The proxy cache size should now be specified *without* adjusting for the number of client hosts; Polygraph will do all the adjustments for you! Index: src/pgl/BenchSym.cc =================================================================== RCS file: /usr/local/CVS/polygraph/src/pgl/Attic/BenchSym.cc,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 BenchSym.cc --- src/pgl/BenchSym.cc 2000/06/26 21:29:23 1.1.2.2 +++ src/pgl/BenchSym.cc 2000/07/13 15:27:15 @@ -17,6 +17,7 @@ #include "xstd/String.h" #include "pgl/PglRec.h" +#include "pgl/PglIntSym.h" #include "pgl/PglNetAddrSym.h" #include "pgl/PglArraySym.h" #include "pgl/PglNetAddrRange.h" @@ -24,9 +25,10 @@ BenchSym::BenchSym(): RecSym("Bench", new PglRec) { + theRec->bAdd("rate", "peak_req_rate", 0); + theRec->bAdd("int", "client_host_count", 0); theRec->bAdd("addr", "client_addr_mask", 0); theRec->bAdd("addr", "server_addr_mask", 0); - theRec->bAdd("rate", "peak_req_rate", 0); theRec->bAdd("rate", "max_client_load", 0); theRec->bAdd("rate", "max_robot_load", 0); } @@ -44,6 +46,14 @@ return RecSym::clone(type); } +bool BenchSym::peakReqRate(double &rate) const { + return getRate("peak_req_rate", rate); +} + +bool BenchSym::clientHostCount(int &count) const { + return getInt("client_host_count", count); +} + NetAddr BenchSym::cltMask() const { return getNetAddr("client_addr_mask"); } @@ -52,16 +62,25 @@ return getNetAddr("server_addr_mask"); } -bool BenchSym::peakReqRate(double &rate) const { - return getRate("peak_req_rate", rate); -} - bool BenchSym::maxCltLoad(double &load) const { return getRate("max_client_load", load); } bool BenchSym::maxRbtLoad(double &load) const { return getRate("max_robot_load", load); +} + +IntSym *BenchSym::clientHostCount() const { + int count = -1; + if (getInt("client_host_count", count)) + return new IntSym(count); + + // calculate, if possible + double reqRate, cltLoad; + if (!peakReqRate(reqRate) || !maxCltLoad(cltLoad) || cltLoad <= 0) + return 0; + + return new IntSym((int)ceil(reqRate/cltLoad)); } ArraySym *BenchSym::robots() const { Index: src/pgl/BenchSym.h =================================================================== RCS file: /usr/local/CVS/polygraph/src/pgl/Attic/BenchSym.h,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 BenchSym.h --- src/pgl/BenchSym.h 2000/06/23 03:50:28 1.1.2.1 +++ src/pgl/BenchSym.h 2000/07/13 15:26:56 @@ -17,6 +17,7 @@ #include "pgl/PglRecSym.h" class String; +class IntSym; class PglArraySym; @@ -29,12 +30,14 @@ virtual bool isA(const String &type) const; virtual SynSym *clone(const String &type) const; + bool peakReqRate(double &rate) const; + bool clientHostCount(int &count) const; NetAddr cltMask() const; NetAddr srvMask() const; - bool peakReqRate(double &rate) const; bool maxCltLoad(double &load) const; bool maxRbtLoad(double &load) const; + IntSym *clientHostCount() const; ArraySym *robots() const; ArraySym *servers() const; Index: src/pgl/PglSemx.cc =================================================================== RCS file: /usr/local/CVS/polygraph/src/pgl/PglSemx.cc,v retrieving revision 1.2.2.7 diff -u -r1.2.2.7 PglSemx.cc --- src/pgl/PglSemx.cc 2000/07/11 19:16:13 1.2.2.7 +++ src/pgl/PglSemx.cc 2000/07/13 15:31:08 @@ -404,6 +404,15 @@ CheckArgs(fname, 0, args); return new UniqIdSym(UniqId::Create()); } else + if (!strcmp(fname.spelling(), "clientHostCount")) { + CheckArgs(fname, 1, args); + CheckArg(fname, 0, args, "Bench"); + if (IntSym *is = ((BenchSym&)args[0]->cast("Bench")).clientHostCount()) + return is; + cerr << fname.loc() << "clientHostCount(): cannot compute " + << "number of client hosts using the given bench configuration; " + << "are peak_req_rate and max_client_load set?" << endl << xexit; + } else if (!strcmp(fname.spelling(), "robotAddrs")) { CheckArgs(fname, 1, args); CheckArg(fname, 0, args, "Bench"); Index: workloads/polymix-3.pg =================================================================== RCS file: /usr/local/CVS/polygraph/workloads/polymix-3.pg,v retrieving revision 1.1.2.10 diff -u -r1.1.2.10 polymix-3.pg --- workloads/polymix-3.pg 2000/07/12 06:31:17 1.1.2.10 +++ workloads/polymix-3.pg 2000/07/13 15:41:11 @@ -8,26 +8,29 @@ Bench TheBench = benchPolyMix3; // start with the default settings - /* If needed, you can specify a different mask for IP aliases. * For example, TheBench.server_addr_mask = '10.13.0.0:8080'; */ + +/* All parameters must be set from the proxy point of view. + * Polygraph will calculate the required number of client-server + * pairs and adjust individual pair configuration accordingly. */ + -/* Set your peak request rate here. For example: 100/sec. +/* Set your total peak request rate here. For example: 100/sec. * Polygraph will use TheBench to figure out which IP aliases to use. - * You must have the aliases configured before running a test */ + * You must have the aliases configured before running a test. */ TheBench.peak_req_rate = undef(); -/* ProxyCacheSize is used for the cache-filling phase. Each polyclt process - * is responsible for filling some fraction of the cache. Set the - * ProxyCacheSize to the total cache size (disk + RAM), divided by the number - * of polyclts processes. For example: 30GB/2. */ -size ProxyCacheSize = undef() / undef(); +/* Set the total cache size (disk + RAM). For example: 30GB. + * ProxyCacheSize is used for the cache-filling phase. */ +size ProxyCacheSize = undef(); -/* Fill request rate must be between 10% and 100% of peak_req_rate above - * For example: (50%*TheBench.peak_req_rate) */ +/* Set request rate for the cache-filling phase. + * This rate must be between 10% and 100% of peak_req_rate above. + * For example: (50%*TheBench.peak_req_rate) */ rate FillRate = undef(); Index: workloads/include/polymix-3-guts.pg =================================================================== RCS file: /usr/local/CVS/polygraph/workloads/include/Attic/polymix-3-guts.pg,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 polymix-3-guts.pg --- workloads/include/polymix-3-guts.pg 2000/07/13 06:48:16 1.1.2.2 +++ workloads/include/polymix-3-guts.pg 2000/07/13 15:50:29 @@ -11,6 +11,9 @@ #include "phases.pg" +// compute the number of pairs if not set already +TheBench.client_host_count = clientHostCount(TheBench); + // robots and servers will bind to these addresses addr[] rbt_ips = robotAddrs(TheBench); // or ['127.0.0.1' ** 2 ]; addr[] srv_ips = serverAddrs(TheBench); // or ['127.0.0.1:8080', '127.0.0.1:8888' ]; @@ -74,8 +77,7 @@ float fillable_ratio = 75%; // ~(cachable, not reloaded, HTTP 200 response) rate peak_fill_rate = PeakRate * 0.45 * fillable_ratio; int wsc = int(peak_fill_rate * platDur); // number of objects in the WS -// adjust for the number of benches -working_set_cap(wsc /* XXX benchClients(TheBench) */); +working_set_cap(wsc / TheBench.client_host_count); Phase phWarm = { @@ -94,7 +96,7 @@ Phase phFill = { name = "fill"; - goal.fill_size = 2*ProxyCacheSize; // XXX: adjust to cllients + goal.fill_size = 2*ProxyCacheSize / TheBench.client_host_count; wait_wss_freeze = yes; // will finish only if WSS is frozen };