4 from twisted.internet import reactor, defer
5 from twisted.python import log
6 from twisted.application import service
7 from foolscap.api import Tub, fireEventually
13 DO_MUTABLE_CREATE = True
16 def __init__(self, test_client_dir):
17 #self.real_stderr = sys.stderr
18 log.startLogging(open("st.log", "a"), setStdout=False)
19 f = open(os.path.join(test_client_dir, "private", "control.furl"), "r")
20 self.control_furl = f.read().strip()
22 self.base_service = service.MultiService()
24 self.upload_times = {}
25 self.download_times = {}
30 d.addCallback(lambda res: self.setUp())
31 d.addCallback(lambda res: self.do_test())
32 d.addBoth(self.tearDown)
49 self.base_service.startService()
51 self.tub.setOption("expose-remote-exception-types", False)
52 self.tub.setServiceParent(self.base_service)
53 d = self.tub.getReference(self.control_furl)
55 self.client_rref = rref
56 print "Got Client Control reference"
58 d.addCallback(_gotref)
61 def stall(self, delay, result=None):
63 reactor.callLater(delay, d.callback, result)
66 def record_times(self, times, key):
67 print "TIME (%s): %s up, %s down" % (key, times[0], times[1])
68 self.upload_times[key], self.download_times[key] = times
70 def one_test(self, res, name, count, size, mutable):
71 # values for 'mutable':
72 # False (upload a different CHK file for each 'count')
73 # "create" (upload different contents into a new SSK file)
74 # "upload" (upload different contents into the same SSK file. The
75 # time consumed does not include the creation of the file)
76 d = self.client_rref.callRemote("speed_test", count, size, mutable)
77 d.addCallback(self.record_times, name)
80 def measure_rtt(self, res):
81 # use RIClient.get_nodeid() to measure the foolscap-level RTT
82 d = self.client_rref.callRemote("measure_peer_response_time")
84 assert len(res) # need at least one peer
86 self.total_rtt = sum(times)
87 self.average_rtt = sum(times) / len(times)
88 self.max_rtt = max(times)
89 print "num-peers: %d" % len(times)
90 print "total-RTT: %f" % self.total_rtt
91 print "average-RTT: %f" % self.average_rtt
92 print "max-RTT: %f" % self.max_rtt
99 d = defer.succeed(None)
100 d.addCallback(self.one_test, "startup", 1, 1000, False) #ignore this one
101 d.addCallback(self.measure_rtt)
103 if self.DO_IMMUTABLE:
105 d.addCallback(self.one_test, "1x 200B", 1, 200, False)
106 d.addCallback(self.one_test, "10x 200B", 10, 200, False)
107 def _maybe_do_100x_200B(res):
108 if self.upload_times["10x 200B"] < 5:
109 print "10x 200B test went too fast, doing 100x 200B test"
110 return self.one_test(None, "100x 200B", 100, 200, False)
112 d.addCallback(_maybe_do_100x_200B)
113 d.addCallback(self.one_test, "1MB", 1, 1*MB, False)
114 d.addCallback(self.one_test, "10MB", 1, 10*MB, False)
115 def _maybe_do_100MB(res):
116 if self.upload_times["10MB"] > 30:
117 print "10MB test took too long, skipping 100MB test"
119 return self.one_test(None, "100MB", 1, 100*MB, False)
120 d.addCallback(_maybe_do_100MB)
122 if self.DO_MUTABLE_CREATE:
123 # mutable file creation
124 d.addCallback(self.one_test, "10x 200B SSK creation", 10, 200,
128 # mutable file upload/download
129 d.addCallback(self.one_test, "10x 200B SSK", 10, 200, "upload")
130 def _maybe_do_100x_200B_SSK(res):
131 if self.upload_times["10x 200B SSK"] < 5:
132 print "10x 200B SSK test went too fast, doing 100x 200B SSK"
133 return self.one_test(None, "100x 200B SSK", 100, 200,
136 d.addCallback(_maybe_do_100x_200B_SSK)
137 d.addCallback(self.one_test, "1MB SSK", 1, 1*MB, "upload")
139 d.addCallback(self.calculate_speeds)
142 def calculate_speeds(self, res):
144 # we assume that A*200bytes is negligible
146 if self.DO_IMMUTABLE:
148 if "100x 200B" in self.upload_times:
149 B = self.upload_times["100x 200B"] / 100
151 B = self.upload_times["10x 200B"] / 10
152 print "upload per-file time: %.3fs" % B
153 print "upload per-file times-avg-RTT: %f" % (B / self.average_rtt)
154 print "upload per-file times-total-RTT: %f" % (B / self.total_rtt)
155 A1 = 1*MB / (self.upload_times["1MB"] - B) # in bytes per second
156 print "upload speed (1MB):", self.number(A1, "Bps")
157 A2 = 10*MB / (self.upload_times["10MB"] - B)
158 print "upload speed (10MB):", self.number(A2, "Bps")
159 if "100MB" in self.upload_times:
160 A3 = 100*MB / (self.upload_times["100MB"] - B)
161 print "upload speed (100MB):", self.number(A3, "Bps")
164 if "100x 200B" in self.download_times:
165 B = self.download_times["100x 200B"] / 100
167 B = self.download_times["10x 200B"] / 10
168 print "download per-file time: %.3fs" % B
169 print "download per-file times-avg-RTT: %f" % (B / self.average_rtt)
170 print "download per-file times-total-RTT: %f" % (B / self.total_rtt)
171 A1 = 1*MB / (self.download_times["1MB"] - B) # in bytes per second
172 print "download speed (1MB):", self.number(A1, "Bps")
173 A2 = 10*MB / (self.download_times["10MB"] - B)
174 print "download speed (10MB):", self.number(A2, "Bps")
175 if "100MB" in self.download_times:
176 A3 = 100*MB / (self.download_times["100MB"] - B)
177 print "download speed (100MB):", self.number(A3, "Bps")
179 if self.DO_MUTABLE_CREATE:
181 B = self.upload_times["10x 200B SSK creation"] / 10
182 print "create per-file time SSK: %.3fs" % B
186 if "100x 200B SSK" in self.upload_times:
187 B = self.upload_times["100x 200B SSK"] / 100
189 B = self.upload_times["10x 200B SSK"] / 10
190 print "upload per-file time SSK: %.3fs" % B
191 A1 = 1*MB / (self.upload_times["1MB SSK"] - B) # in bytes per second
192 print "upload speed SSK (1MB):", self.number(A1, "Bps")
195 if "100x 200B SSK" in self.download_times:
196 B = self.download_times["100x 200B SSK"] / 100
198 B = self.download_times["10x 200B SSK"] / 10
199 print "download per-file time SSK: %.3fs" % B
200 A1 = 1*MB / (self.download_times["1MB SSK"] - B) # in bytes per
202 print "download speed SSK (1MB):", self.number(A1, "Bps")
204 def number(self, value, suffix=""):
213 fmt = "%.2fk%s"; scaling = 1e3
215 fmt = "%.2fM%s"; scaling = 1e6
217 fmt = "%.2fG%s"; scaling = 1e9
219 fmt = "%.2fT%s"; scaling = 1e12
221 fmt = "%.2fP%s"; scaling = 1e15
224 return fmt % (value / scaling, suffix)
226 def tearDown(self, res):
227 d = self.base_service.stopService()
228 d.addCallback(lambda ignored: res)
232 if __name__ == '__main__':
233 test_client_dir = sys.argv[1]
234 st = SpeedTest(test_client_dir)