Commit 1fe199cd authored by Matt Traudt's avatar Matt Traudt
Browse files

Make multiple bandwidth measurements

parent 0567cce8
......@@ -24,19 +24,21 @@ class V3BWLine:
self.bw = bw
self.nick = nick
# convert to ms
self.rtts = [int(round(r * 1000)) for r in rtts]
rtts = [round(r * 1000) for r in rtts]
self.rtt = round(median(rtts))
def __str__(self):
frmt = 'node_id={fp} bw={sp} nick={n} min_rtt={rtt}'
frmt = 'node_id={fp} bw={sp} nick={n} rtt={rtt}'
return frmt.format(fp=self.fp, sp=round(self.bw), n=self.nick,
rtt=min(self.rtts))
rtt=self.rtt)
def result_data_to_v3bw_line(data, fingerprint):
assert fingerprint in data
results = data[fingerprint]
nick = results[0]['nickname']
speeds = [r['amount'] / r['duration'] for r in results]
speeds = [dl['amount'] / dl['duration']
for r in results for dl in r['downloads']]
speed = median(speeds)
rtts = [rtt for r in results for rtt in r['rtts']]
return V3BWLine(fingerprint, speed, nick, rtts)
......
......@@ -11,12 +11,11 @@ from datetime import date
class Result:
''' A simple struct to pack a measurement result into so that other code
can be confident it is handling a well-formed result. '''
def __init__(self, relay, circ, server_host, rtts, duration, amount):
def __init__(self, relay, circ, server_host, rtts, download_results):
self._relay = relay
self._circ = circ
self._duration = duration
self._amount = amount
self._server_host = server_host
self._downloads = download_results
self._rtts = rtts
self._time = time.time()
......@@ -45,12 +44,8 @@ class Result:
return self._time
@property
def duration(self):
return self._duration
@property
def amount(self):
return self._amount
def downloads(self):
return self._downloads
@property
def server_host(self):
......@@ -61,8 +56,7 @@ class Result:
'fingerprint': self.fingerprint,
'nickname': self.nickname,
'time': self.time,
'duration': self.duration,
'amount': self.amount,
'downloads': self.downloads,
'address': self.address,
'circ': self.circ,
'rtts': self.rtts,
......@@ -107,8 +101,5 @@ class ResultDump:
fp = result.fingerprint
nick = result.nickname
self.write_result(result)
amount = result.amount
duration = result.duration
rate = amount / duration
rate = rate * 8 / 1024 / 1024
print(fp, nick, rate, duration)
dls = result.downloads
print(fp, nick, dls)
......@@ -19,9 +19,8 @@ stream_building_lock = RLock()
# maximum we want to read per read() call
MAX_RECV_PER_READ = 1*1024*1024
# minimum amount of time a transfer needs to take in order for us to consider
# it a measurement
MIN_TIME_REQUIRED = 5
DOWNLOAD_TIMES = {'toofast': 1, 'min': 5, 'target': 6, 'max': 10}
DESIRED_RESULTS = 5
def fail_hard(*s):
......@@ -148,9 +147,9 @@ def measure_relay(args, cb, rl, relay):
return
# SECOND: measure throughput on this sircuit. Start with what should be a
# small amount
result_time = None
results = []
expected_amount = 16*1024
while result_time is None or result_time < MIN_TIME_REQUIRED:
while len(results) < DESIRED_RESULTS:
# Tell the server to send us the current expected_amount.
if not tell_server_amount(s, expected_amount):
close_socket(s)
......@@ -163,20 +162,21 @@ def measure_relay(args, cb, rl, relay):
close_socket(s)
cb.close_circuit(circ_id)
return
# If it took long enough, make an educated guess about how many bytes
# it should take to have MIN_TIME_REQUIRED seconds to elapse while
# doing so
if result_time > 1:
if result_time < DOWNLOAD_TIMES['toofast']:
expected_amount = int(expected_amount * 10)
elif result_time < DOWNLOAD_TIMES['min']:
expected_amount = int(
expected_amount * MIN_TIME_REQUIRED / result_time * 1.1)
# If it didn't take very long at all, then greatly increase the amount
# to send
expected_amount * DOWNLOAD_TIMES['target'] / result_time)
elif result_time < DOWNLOAD_TIMES['target']:
results.append({'duration': result_time, 'amount': expected_amount})
elif result_time < DOWNLOAD_TIMES['max']:
results.append({'duration': result_time, 'amount': expected_amount})
else:
expected_amount = int(expected_amount * 10)
expected_amount = int(
expected_amount * DOWNLOAD_TIMES['target'] / result_time)
circ = cb.get_circuit_path(circ_id)
cb.close_circuit(circ_id)
return Result(relay, circ, args.server_host, rtts, result_time,
expected_amount)
return Result(relay, circ, args.server_host, rtts, results)
def result_putter(result_dump):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment