2007-09-20 01:27:47 +00:00
|
|
|
#! /bin/env/python
|
|
|
|
|
|
|
|
import os, sys
|
|
|
|
from twisted.internet import reactor, defer
|
|
|
|
from twisted.python import log
|
|
|
|
from twisted.application import service
|
|
|
|
from foolscap import Tub, eventual
|
|
|
|
|
2007-09-20 23:55:33 +00:00
|
|
|
MB = 1000000
|
|
|
|
|
2007-09-20 01:27:47 +00:00
|
|
|
class SpeedTest:
|
|
|
|
def __init__(self, test_client_dir):
|
|
|
|
#self.real_stderr = sys.stderr
|
|
|
|
log.startLogging(open("st.log", "a"), setStdout=False)
|
|
|
|
f = open(os.path.join(test_client_dir, "control.furl"), "r")
|
|
|
|
self.control_furl = f.read().strip()
|
|
|
|
f.close()
|
|
|
|
self.base_service = service.MultiService()
|
|
|
|
self.failed = None
|
2007-09-21 01:52:44 +00:00
|
|
|
self.upload_times = {}
|
|
|
|
self.download_times = {}
|
2007-09-20 01:27:47 +00:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
print "STARTING"
|
|
|
|
d = eventual.fireEventually()
|
|
|
|
d.addCallback(lambda res: self.setUp())
|
|
|
|
d.addCallback(lambda res: self.do_test())
|
|
|
|
d.addBoth(self.tearDown)
|
|
|
|
def _err(err):
|
|
|
|
self.failed = err
|
|
|
|
log.err(err)
|
|
|
|
print err
|
|
|
|
d.addErrback(_err)
|
|
|
|
def _done(res):
|
|
|
|
reactor.stop()
|
|
|
|
return res
|
|
|
|
d.addBoth(_done)
|
|
|
|
reactor.run()
|
|
|
|
if self.failed:
|
|
|
|
print "EXCEPTION"
|
|
|
|
print self.failed
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.base_service.startService()
|
|
|
|
self.tub = Tub()
|
|
|
|
self.tub.setServiceParent(self.base_service)
|
|
|
|
d = self.tub.getReference(self.control_furl)
|
|
|
|
def _gotref(rref):
|
|
|
|
self.client_rref = rref
|
|
|
|
print "Got Client Control reference"
|
|
|
|
return self.stall(5)
|
|
|
|
d.addCallback(_gotref)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def stall(self, delay, result=None):
|
|
|
|
d = defer.Deferred()
|
|
|
|
reactor.callLater(delay, d.callback, result)
|
|
|
|
return d
|
|
|
|
|
2007-09-21 01:52:44 +00:00
|
|
|
def record_times(self, times, key):
|
|
|
|
print "TIME (%s): %s up, %s down" % (key, times[0], times[1])
|
|
|
|
self.upload_times[key], self.download_times[key] = times
|
2007-09-20 01:40:18 +00:00
|
|
|
|
2007-09-20 23:55:33 +00:00
|
|
|
def one_test(self, res, name, count, size):
|
2007-09-21 01:52:44 +00:00
|
|
|
d = self.client_rref.callRemote("speed_test", count, size)
|
|
|
|
d.addCallback(self.record_times, name)
|
2007-09-20 23:55:33 +00:00
|
|
|
return d
|
|
|
|
|
2007-09-20 01:27:47 +00:00
|
|
|
def do_test(self):
|
|
|
|
print "doing test"
|
2007-09-20 01:40:18 +00:00
|
|
|
rr = self.client_rref
|
2007-09-21 01:52:44 +00:00
|
|
|
d = defer.succeed(None)
|
2007-09-20 23:55:33 +00:00
|
|
|
d.addCallback(self.one_test, "startup", 1, 1000) # ignore this one
|
|
|
|
d.addCallback(self.one_test, "1x 200B", 1, 200)
|
|
|
|
d.addCallback(self.one_test, "10x 200B", 10, 200)
|
2007-09-26 01:57:36 +00:00
|
|
|
def _maybe_do_100x_200B(res):
|
|
|
|
if self.upload_times["10x 200B"] < 5:
|
|
|
|
print "10x 200B test went too fast, doing 100x 200B test"
|
|
|
|
return self.one_test(None, "100x 200B", 100, 200)
|
|
|
|
return
|
|
|
|
d.addCallback(_maybe_do_100x_200B)
|
2007-09-20 23:55:33 +00:00
|
|
|
d.addCallback(self.one_test, "1MB", 1, 1*MB)
|
|
|
|
d.addCallback(self.one_test, "10MB", 1, 10*MB)
|
2007-09-22 07:04:46 +00:00
|
|
|
def _maybe_do_100MB(res):
|
|
|
|
if self.upload_times["10MB"] > 30:
|
|
|
|
print "10MB test took too long, skipping 100MB test"
|
|
|
|
return
|
|
|
|
return self.one_test(None, "100MB", 1, 100*MB)
|
|
|
|
d.addCallback(_maybe_do_100MB)
|
2007-09-21 01:52:44 +00:00
|
|
|
d.addCallback(self.calculate_speeds)
|
2007-09-20 01:27:47 +00:00
|
|
|
return d
|
|
|
|
|
2007-09-21 01:52:44 +00:00
|
|
|
def calculate_speeds(self, res):
|
2007-09-20 23:55:33 +00:00
|
|
|
# time = A*size+B
|
|
|
|
# we assume that A*200bytes is negligible
|
2007-09-21 01:52:44 +00:00
|
|
|
|
|
|
|
# upload
|
2007-09-26 01:57:36 +00:00
|
|
|
if "100x 200B" in self.upload_times:
|
|
|
|
B = self.upload_times["100x 200B"] / 100
|
|
|
|
else:
|
|
|
|
B = self.upload_times["10x 200B"] / 10
|
2007-09-21 01:52:44 +00:00
|
|
|
print "upload per-file time: %.3fs" % B
|
|
|
|
A1 = 1*MB / (self.upload_times["1MB"] - B) # in bytes per second
|
|
|
|
print "upload speed (1MB):", self.number(A1, "Bps")
|
|
|
|
A2 = 10*MB / (self.upload_times["10MB"] - B)
|
|
|
|
print "upload speed (10MB):", self.number(A2, "Bps")
|
2007-09-22 07:04:46 +00:00
|
|
|
if "100MB" in self.upload_times:
|
|
|
|
A3 = 100*MB / (self.upload_times["100MB"] - B)
|
|
|
|
print "upload speed (100MB):", self.number(A3, "Bps")
|
2007-09-21 01:52:44 +00:00
|
|
|
|
|
|
|
# download
|
2007-09-26 01:57:36 +00:00
|
|
|
if "100x 200B" in self.download_times:
|
|
|
|
B = self.download_times["100x 200B"] / 100
|
|
|
|
else:
|
|
|
|
B = self.download_times["10x 200B"] / 10
|
2007-09-21 01:52:44 +00:00
|
|
|
print "download per-file time: %.3fs" % B
|
|
|
|
A1 = 1*MB / (self.download_times["1MB"] - B) # in bytes per second
|
|
|
|
print "download speed (1MB):", self.number(A1, "Bps")
|
|
|
|
A2 = 10*MB / (self.download_times["10MB"] - B)
|
|
|
|
print "download speed (10MB):", self.number(A2, "Bps")
|
2007-09-22 07:04:46 +00:00
|
|
|
if "100MB" in self.download_times:
|
|
|
|
A3 = 100*MB / (self.download_times["100MB"] - B)
|
|
|
|
print "download speed (100MB):", self.number(A3, "Bps")
|
2007-09-20 23:55:33 +00:00
|
|
|
|
|
|
|
def number(self, value, suffix=""):
|
|
|
|
scaling = 1
|
|
|
|
if value < 1:
|
|
|
|
fmt = "%1.2g%s"
|
|
|
|
elif value < 100:
|
|
|
|
fmt = "%.1f%s"
|
|
|
|
elif value < 1000:
|
|
|
|
fmt = "%d%s"
|
|
|
|
elif value < 1e6:
|
|
|
|
fmt = "%.2fk%s"; scaling = 1e3
|
|
|
|
elif value < 1e9:
|
|
|
|
fmt = "%.2fM%s"; scaling = 1e6
|
|
|
|
elif value < 1e12:
|
|
|
|
fmt = "%.2fG%s"; scaling = 1e9
|
|
|
|
elif value < 1e15:
|
|
|
|
fmt = "%.2fT%s"; scaling = 1e12
|
|
|
|
elif value < 1e18:
|
|
|
|
fmt = "%.2fP%s"; scaling = 1e15
|
|
|
|
else:
|
|
|
|
fmt = "huge! %g%s"
|
|
|
|
return fmt % (value / scaling, suffix)
|
|
|
|
|
2007-09-20 01:27:47 +00:00
|
|
|
def tearDown(self, res):
|
|
|
|
d = self.base_service.stopService()
|
|
|
|
d.addCallback(lambda ignored: res)
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
test_client_dir = sys.argv[1]
|
|
|
|
st = SpeedTest(test_client_dir)
|
|
|
|
st.run()
|