commit 42948a36f82b5d38223cb4691bc25a84b809e11a Author: Zack Weinberg zackw@panix.com Date: Wed Feb 15 08:01:37 2012 -0800
Another round of adjustments to the benchmarks --- scripts/benchmark.py | 49 +++++++++++++++++-------- scripts/bm-fixedrate-cgi.c | 31 ++++++++-------- scripts/bm-tor-controller.py | 83 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 32 deletions(-)
diff --git a/scripts/benchmark.py b/scripts/benchmark.py index f4f8830..be45467 100755 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -46,10 +46,10 @@ PROXY_SSH_CMD = ("ssh", PROXY)
TARGET = "storustest.nfshost.com"
-# Fudge factors. For some reason, bm-fixedrate generates data a -# linear factor slower than it was meant to; this is the quick fix. +# For some reason, bm-fixedrate generates data a linear factor slower +# than it was meant to; this is the quick fix.
-FUDGE_FIXEDRATE = 2.5 +FUDGE_FIXEDRATE = 1.939
# Programs we need to run. Change these if any binary is not in the # default path or hasn't got the default name. @@ -58,7 +58,6 @@ FUDGE_FIXEDRATE = 2.5 # setup, write a wrapper script.
C_bwm = "bwm-ng" -C_curl = "curl" C_mcurl = "bm-mcurl" C_storus = "stegotorus-wrapper" C_tor = "/usr/sbin/tor" @@ -232,10 +231,13 @@ def p_tor_direct(): ORPort %s SocksPort 0 BridgeRelay 1 +AssumeReachable 1 PublishServerDescriptor 0 ExitPolicy reject *:* DataDirectory . Log err stderr +ContactInfo zackw at cmu dot edu +Nickname storustest # unfortunately there doesn't seem to be any way to tell Tor to accept # OR connections from specific IP addresses only. """ % PROXY_PORT) @@ -268,17 +270,24 @@ Log err stderr Bridge %s:%s UseBridges 1 SafeSocks 0 +ControlPort 9051 +__DisablePredictedCircuits 1 +__LeaveStreamsUnattached 1 """ % (PROXY_PORT, PROXY_IP, PROXY_PORT)) fp.close() return ClientProcess((C_tor, "--quiet", "-f", "tor-direct-client.conf"))
+def c_torctl(): + return ClientProcess((os.path.dirname(__file__) + '/bm-tor-controller.py')) + def c_curl(url, proxyhost): - return ClientProcess((C_curl, "-s", "--socks5-hostname", + return ClientProcess((C_mcurl, '1', '1', proxyhost + ":" + PROXY_PORT, - url, "-o", "/dev/null")) + url))
def c_mcurl(prefix, cps, proxyhost): - return ClientProcess((C_mcurl, str(cps), '200', proxyhost, + return ClientProcess((C_mcurl, str(cps), '200', + proxyhost + ':' + PROXY_PORT, 'http://' + TARGET + '/' + prefix + '/[0-9]/[0-9]/[0-9]/[0-9].html'))
@@ -296,7 +305,7 @@ def bench_fixedrate_direct(report): client = c_curl('http://' + TARGET + '/bm-fixedrate.cgi/' + str(int(cap * 1000 * FUDGE_FIXEDRATE)), PROXY) - monitor(report, "fixedrate,direct,%d" % cap, 60) + monitor(report, "fixedrate,direct,%d" % cap, 10) finally: if client is not None: client.terminate() @@ -314,6 +323,7 @@ def bench_fixedrate_tor(report): try: proxy = p_tor_direct() proxyl = c_tor_direct() + proxyc = c_torctl() time.sleep(5) # tor startup is slow
for cap in range(10,810,10): @@ -332,17 +342,20 @@ def bench_fixedrate_tor(report): if proxy is not None: proxy.terminate() proxy.wait() + if proxyc is not None: + proxyc.terminate() + proxyc.wait() if proxyl is not None: proxyl.terminate() proxyl.wait()
-def bench_files_direct(report, prefix): +def bench_files_direct(report, prefix, maxconn): client = None proxy = None try: proxy = p_nylon()
- for cps in range(1,151): + for cps in range(1,maxconn+1): sys.stderr.write("files.%s,direct,%d\n" % (prefix, cps)) try: client = c_mcurl(prefix, cps, PROXY_IP) @@ -357,16 +370,17 @@ def bench_files_direct(report, prefix): proxy.terminate() proxy.wait()
-def bench_files_tor(report, prefix): +def bench_files_tor(report, prefix, maxconn): client = None proxy = None proxyl = None try: proxy = p_tor_direct() proxyl = c_tor_direct() + proxyc = c_torctl() time.sleep(5) # tor startup is slow
- for cps in range(1,151): + for cps in range(1,maxconn+1): sys.stderr.write("files.%s,tor,%d\n" % (prefix, cps)) try: client = c_mcurl(prefix, cps, '127.0.0.1') @@ -380,6 +394,9 @@ def bench_files_tor(report, prefix): if proxy is not None: proxy.terminate() proxy.wait() + if proxyc is not None: + proxyc.terminate() + proxyc.wait() if proxyl is not None: proxyl.terminate() proxyl.wait() @@ -388,7 +405,7 @@ if __name__ == '__main__': sys.stdout.write("benchmark,relay,cap,obs,up,down\n") bench_fixedrate_direct(sys.stdout) bench_fixedrate_tor(sys.stdout) - bench_files_direct(sys.stdout, "fixed") - bench_files_tor(sys.stdout, "fixed") - bench_files_direct(sys.stdout, "pareto") - bench_files_tor(sys.stdout, "pareto") + bench_files_direct(sys.stdout, "fixed", 120) + bench_files_tor(sys.stdout, "fixed", 120) + bench_files_direct(sys.stdout, "pareto", 80) + bench_files_tor(sys.stdout, "pareto", 80) diff --git a/scripts/bm-fixedrate-cgi.c b/scripts/bm-fixedrate-cgi.c index 2b48f98..851cda7 100644 --- a/scripts/bm-fixedrate-cgi.c +++ b/scripts/bm-fixedrate-cgi.c @@ -13,10 +13,6 @@ #include <time.h> #include <unistd.h>
-/* 1400 bytes is a safe figure for per-packet transmissible payload. */ -#define BLOCKSZ 1400 - - #if __GNUC__ >= 3 #define NORETURN void __attribute__((noreturn)) #else @@ -48,14 +44,22 @@ error_500(const char *syscall) static void generate(unsigned long rate, bool dryrun) { - double interval; timer_t timerid; struct sigevent sev; struct itimerspec its; sigset_t mask; int sig; char *data; - size_t bufsz = BLOCKSZ; + size_t bufsz; + + /* Despite our use of the high-resolution interval timers, we cannot + count on being scheduled more often than 1/CLOCKS_PER_SEC + seconds. We ask to be scheduled every 0.01 seconds to avoid a + class of rounding errors, since it is very likely that we will be + asked to generate at a rate that is a power of ten. + + Therefore, every time we are scheduled we should produce R/100 + bytes of data. */
/* You send data at R bytes per second in 1400-byte blocks by calling write() every 1/(R/1400) second. However, despite our @@ -63,24 +67,19 @@ generate(unsigned long rate, bool dryrun) being scheduled more often than every 1/CLOCKS_PER_SEC seconds, so if we need to send data faster than that, bump up the block size instead. */ - interval = 1./(rate/(double)BLOCKSZ); - - if (interval < 1./CLOCKS_PER_SEC) { - interval = 1./CLOCKS_PER_SEC; - bufsz = rate / CLOCKS_PER_SEC; - } + bufsz = rate / 100;
- its.it_value.tv_sec = lrint(floor(interval)); - its.it_value.tv_nsec = lrint((interval - its.it_value.tv_sec) * 1e9); + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 10000000; /* 1e7 ns = 0.01 s */ its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (dryrun) { printf("Content-Type: text/plain\n\n" "Goal %lu bytes per second:\n" - "would send %lu bytes every %f seconds\n" + "would send %zu bytes every 0.01 seconds\n" " " " " " " %lu sec + %lu nsec\n", - rate, bufsz, interval, + rate, bufsz, (unsigned long)its.it_value.tv_sec, (unsigned long)its.it_value.tv_nsec); return; diff --git a/scripts/bm-tor-controller.py b/scripts/bm-tor-controller.py new file mode 100755 index 0000000..1b147be --- /dev/null +++ b/scripts/bm-tor-controller.py @@ -0,0 +1,83 @@ +#! /usr/bin/python + +from torctl import TorCtl, TorUtil, PathSupport + +import time + +i = PathSupport.IdHexRestriction + +# in San Francisco +amunet = PathSupport.OrNodeRestriction([ + i('$0CE3CFB1E9CC47B63EA8869813BF6FAB7D4540C1'), # amunet4 + i('$E0BD57A11F00041A9789577C53A1B784473669E4'), # amunet3 + i('$E5E3E9A472EAF7BE9682B86E92305DB4C71048EF') # amunet2 +]) + +# probably in L.A. +hazare = PathSupport.OrNodeRestriction([ + i('$3D0FAFB36EB9FC9D1EFD68758E2B0025117D3D1B'), # hazare2 + i('$6586CEE14353DD1E6FAF3F172A23B00119A67C57'), # saeed + i('$6F383C2629471E1AE7DA053D04625AAED69844CC') # hazare +]) + +# very likely in L.A. +noisebr = PathSupport.OrNodeRestriction([ + i('$3A415473854F9F082F16EECDFE436218FE1169EA'), # noiseexit01c + i('$9C98B38FE270546C69205E16047B8D46BBBB0447'), # noiseexit01d + i('$F97F3B153FED6604230CD497A3D1E9815B007636') # noiseexit01a +]) + +# I shouldn't have to do this +class TheseUniformly(PathSupport.BaseSelectionManager): + def __init__(self, res_entry, res_mid, res_exit): + PathSupport.BaseSelectionManager.__init__(self) + if not isinstance(res_entry, PathSupport.NodeRestrictionList): + res_entry = PathSupport.NodeRestrictionList([res_entry]) + if not isinstance(res_mid, PathSupport.NodeRestrictionList): + res_mid = PathSupport.NodeRestrictionList([res_mid]) + if not isinstance(res_exit, PathSupport.NodeRestrictionList): + res_exit = PathSupport.NodeRestrictionList([res_exit]) + self.res_entry = res_entry + self.res_mid = res_mid + self.res_exit = res_exit + self.path_selector = None + + def reconfigure(self, consensus): + if self.path_selector is not None: + try: + self.path_selector.rebuild_gens(consensus.sorted_r) + except NoNodesRemain: + pass + + self.path_selector = PathSupport.PathSelector( + PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_entry), + PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_mid), + PathSupport.ExactUniformGenerator(consensus.sorted_r, self.res_exit), + PathSupport.PathRestrictionList([PathSupport.UniqueRestriction()])) + + def new_consensus(self, consensus): + self.reconfigure(consensus) + + def set_exit(self, exit_name): + pass + + def set_target(self, host, port): + pass + + def select_path(self): + return self.path_selector.select_path(3) + +TorUtil.loglevel = "WARN" + +s = TheseUniformly(amunet, hazare, noisebr) +c = TorCtl.connect(ConnClass=PathSupport.Connection) +h = PathSupport.PathBuilder(c, s) +c.set_event_handler(h) +c.set_events([TorCtl.EVENT_TYPE.STREAM, + TorCtl.EVENT_TYPE.BW, + TorCtl.EVENT_TYPE.NEWCONSENSUS, + TorCtl.EVENT_TYPE.NEWDESC, + TorCtl.EVENT_TYPE.CIRC, + TorCtl.EVENT_TYPE.STREAM_BW], True) + +while True: time.sleep(120)
tor-commits@lists.torproject.org