2 from twisted.internet import reactor, defer
3 from twisted.python import log
4 from twisted.application import service
5 from foolscap.api import Tub, fireEventually
11 DO_MUTABLE_CREATE = True
14 def __init__(self, test_client_dir):
15 #self.real_stderr = sys.stderr
16 log.startLogging(open("st.log", "a"), setStdout=False)
17 f = open(os.path.join(test_client_dir, "private", "control.furl"), "r")
18 self.control_furl = f.read().strip()
20 self.base_service = service.MultiService()
22 self.upload_times = {}
23 self.download_times = {}
28 d.addCallback(lambda res: self.setUp())
29 d.addCallback(lambda res: self.do_test())
30 d.addBoth(self.tearDown)
47 self.base_service.startService()
49 self.tub.setOption("expose-remote-exception-types", False)
50 self.tub.setServiceParent(self.base_service)
51 d = self.tub.getReference(self.control_furl)
53 self.client_rref = rref
54 print "Got Client Control reference"
56 d.addCallback(_gotref)
59 def stall(self, delay, result=None):
61 reactor.callLater(delay, d.callback, result)
64 def record_times(self, times, key):
65 print "TIME (%s): %s up, %s down" % (key, times[0], times[1])
66 self.upload_times[key], self.download_times[key] = times
68 def one_test(self, res, name, count, size, mutable):
69 # values for 'mutable':
70 # False (upload a different CHK file for each 'count')
71 # "create" (upload different contents into a new SSK file)
72 # "upload" (upload different contents into the same SSK file. The
73 # time consumed does not include the creation of the file)
74 d = self.client_rref.callRemote("speed_test", count, size, mutable)
75 d.addCallback(self.record_times, name)
78 def measure_rtt(self, res):
79 # use RIClient.get_nodeid() to measure the foolscap-level RTT
80 d = self.client_rref.callRemote("measure_peer_response_time")
82 assert len(res) # need at least one peer
84 self.total_rtt = sum(times)
85 self.average_rtt = sum(times) / len(times)
86 self.max_rtt = max(times)
87 print "num-peers: %d" % len(times)
88 print "total-RTT: %f" % self.total_rtt
89 print "average-RTT: %f" % self.average_rtt
90 print "max-RTT: %f" % self.max_rtt
96 d = defer.succeed(None)
97 d.addCallback(self.one_test, "startup", 1, 1000, False) #ignore this one
98 d.addCallback(self.measure_rtt)
100 if self.DO_IMMUTABLE:
102 d.addCallback(self.one_test, "1x 200B", 1, 200, False)
103 d.addCallback(self.one_test, "10x 200B", 10, 200, False)
104 def _maybe_do_100x_200B(res):
105 if self.upload_times["10x 200B"] < 5:
106 print "10x 200B test went too fast, doing 100x 200B test"
107 return self.one_test(None, "100x 200B", 100, 200, False)
109 d.addCallback(_maybe_do_100x_200B)
110 d.addCallback(self.one_test, "1MB", 1, 1*MB, False)
111 d.addCallback(self.one_test, "10MB", 1, 10*MB, False)
112 def _maybe_do_100MB(res):
113 if self.upload_times["10MB"] > 30:
114 print "10MB test took too long, skipping 100MB test"
116 return self.one_test(None, "100MB", 1, 100*MB, False)
117 d.addCallback(_maybe_do_100MB)
119 if self.DO_MUTABLE_CREATE:
120 # mutable file creation
121 d.addCallback(self.one_test, "10x 200B SSK creation", 10, 200,
125 # mutable file upload/download
126 d.addCallback(self.one_test, "10x 200B SSK", 10, 200, "upload")
127 def _maybe_do_100x_200B_SSK(res):
128 if self.upload_times["10x 200B SSK"] < 5:
129 print "10x 200B SSK test went too fast, doing 100x 200B SSK"
130 return self.one_test(None, "100x 200B SSK", 100, 200,
133 d.addCallback(_maybe_do_100x_200B_SSK)
134 d.addCallback(self.one_test, "1MB SSK", 1, 1*MB, "upload")
136 d.addCallback(self.calculate_speeds)
139 def calculate_speeds(self, res):
141 # we assume that A*200bytes is negligible
143 if self.DO_IMMUTABLE:
145 if "100x 200B" in self.upload_times:
146 B = self.upload_times["100x 200B"] / 100
148 B = self.upload_times["10x 200B"] / 10
149 print "upload per-file time: %.3fs" % B
150 print "upload per-file times-avg-RTT: %f" % (B / self.average_rtt)
151 print "upload per-file times-total-RTT: %f" % (B / self.total_rtt)
152 A1 = 1*MB / (self.upload_times["1MB"] - B) # in bytes per second
153 print "upload speed (1MB):", self.number(A1, "Bps")
154 A2 = 10*MB / (self.upload_times["10MB"] - B)
155 print "upload speed (10MB):", self.number(A2, "Bps")
156 if "100MB" in self.upload_times:
157 A3 = 100*MB / (self.upload_times["100MB"] - B)
158 print "upload speed (100MB):", self.number(A3, "Bps")
161 if "100x 200B" in self.download_times:
162 B = self.download_times["100x 200B"] / 100
164 B = self.download_times["10x 200B"] / 10
165 print "download per-file time: %.3fs" % B
166 print "download per-file times-avg-RTT: %f" % (B / self.average_rtt)
167 print "download per-file times-total-RTT: %f" % (B / self.total_rtt)
168 A1 = 1*MB / (self.download_times["1MB"] - B) # in bytes per second
169 print "download speed (1MB):", self.number(A1, "Bps")
170 A2 = 10*MB / (self.download_times["10MB"] - B)
171 print "download speed (10MB):", self.number(A2, "Bps")
172 if "100MB" in self.download_times:
173 A3 = 100*MB / (self.download_times["100MB"] - B)
174 print "download speed (100MB):", self.number(A3, "Bps")
176 if self.DO_MUTABLE_CREATE:
178 B = self.upload_times["10x 200B SSK creation"] / 10
179 print "create per-file time SSK: %.3fs" % B
183 if "100x 200B SSK" in self.upload_times:
184 B = self.upload_times["100x 200B SSK"] / 100
186 B = self.upload_times["10x 200B SSK"] / 10
187 print "upload per-file time SSK: %.3fs" % B
188 A1 = 1*MB / (self.upload_times["1MB SSK"] - B) # in bytes per second
189 print "upload speed SSK (1MB):", self.number(A1, "Bps")
192 if "100x 200B SSK" in self.download_times:
193 B = self.download_times["100x 200B SSK"] / 100
195 B = self.download_times["10x 200B SSK"] / 10
196 print "download per-file time SSK: %.3fs" % B
197 A1 = 1*MB / (self.download_times["1MB SSK"] - B) # in bytes per
199 print "download speed SSK (1MB):", self.number(A1, "Bps")
201 def number(self, value, suffix=""):
210 fmt = "%.2fk%s"; scaling = 1e3
212 fmt = "%.2fM%s"; scaling = 1e6
214 fmt = "%.2fG%s"; scaling = 1e9
216 fmt = "%.2fT%s"; scaling = 1e12
218 fmt = "%.2fP%s"; scaling = 1e15
221 return fmt % (value / scaling, suffix)
223 def tearDown(self, res):
224 d = self.base_service.stopService()
225 d.addCallback(lambda ignored: res)
229 if __name__ == '__main__':
230 test_client_dir = sys.argv[1]
231 st = SpeedTest(test_client_dir)