]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/test/check_speed.py
remove interpreter shbang lines from non-executables
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / check_speed.py
1 import os, sys
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
6
7 MB = 1000000
8
9 class SpeedTest:
10     DO_IMMUTABLE = True
11     DO_MUTABLE_CREATE = True
12     DO_MUTABLE = True
13
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()
19         f.close()
20         self.base_service = service.MultiService()
21         self.failed = None
22         self.upload_times = {}
23         self.download_times = {}
24
25     def run(self):
26         print "STARTING"
27         d = fireEventually()
28         d.addCallback(lambda res: self.setUp())
29         d.addCallback(lambda res: self.do_test())
30         d.addBoth(self.tearDown)
31         def _err(err):
32             self.failed = err
33             log.err(err)
34             print err
35         d.addErrback(_err)
36         def _done(res):
37             reactor.stop()
38             return res
39         d.addBoth(_done)
40         reactor.run()
41         if self.failed:
42             print "EXCEPTION"
43             print self.failed
44             sys.exit(1)
45
46     def setUp(self):
47         self.base_service.startService()
48         self.tub = Tub()
49         self.tub.setOption("expose-remote-exception-types", False)
50         self.tub.setServiceParent(self.base_service)
51         d = self.tub.getReference(self.control_furl)
52         def _gotref(rref):
53             self.client_rref = rref
54             print "Got Client Control reference"
55             return self.stall(5)
56         d.addCallback(_gotref)
57         return d
58
59     def stall(self, delay, result=None):
60         d = defer.Deferred()
61         reactor.callLater(delay, d.callback, result)
62         return d
63
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
67
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)
76         return d
77
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")
81         def _got(res):
82             assert len(res) # need at least one peer
83             times = res.values()
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
91         d.addCallback(_got)
92         return d
93
94     def do_test(self):
95         print "doing test"
96         d = defer.succeed(None)
97         d.addCallback(self.one_test, "startup", 1, 1000, False) #ignore this one
98         d.addCallback(self.measure_rtt)
99
100         if self.DO_IMMUTABLE:
101             # immutable files
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)
108                 return
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"
115                     return
116                 return self.one_test(None, "100MB", 1, 100*MB, False)
117             d.addCallback(_maybe_do_100MB)
118
119         if self.DO_MUTABLE_CREATE:
120             # mutable file creation
121             d.addCallback(self.one_test, "10x 200B SSK creation", 10, 200,
122                           "create")
123
124         if self.DO_MUTABLE:
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,
131                                          "upload")
132                 return
133             d.addCallback(_maybe_do_100x_200B_SSK)
134             d.addCallback(self.one_test, "1MB SSK", 1, 1*MB, "upload")
135
136         d.addCallback(self.calculate_speeds)
137         return d
138
139     def calculate_speeds(self, res):
140         # time = A*size+B
141         # we assume that A*200bytes is negligible
142
143         if self.DO_IMMUTABLE:
144             # upload
145             if "100x 200B" in self.upload_times:
146                 B = self.upload_times["100x 200B"] / 100
147             else:
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")
159
160             # download
161             if "100x 200B" in self.download_times:
162                 B = self.download_times["100x 200B"] / 100
163             else:
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")
175
176         if self.DO_MUTABLE_CREATE:
177             # SSK creation
178             B = self.upload_times["10x 200B SSK creation"] / 10
179             print "create per-file time SSK: %.3fs" % B
180
181         if self.DO_MUTABLE:
182             # upload SSK
183             if "100x 200B SSK" in self.upload_times:
184                 B = self.upload_times["100x 200B SSK"] / 100
185             else:
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")
190
191             # download SSK
192             if "100x 200B SSK" in self.download_times:
193                 B = self.download_times["100x 200B SSK"] / 100
194             else:
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
198                                                              # second
199             print "download speed SSK (1MB):", self.number(A1, "Bps")
200
201     def number(self, value, suffix=""):
202         scaling = 1
203         if value < 1:
204             fmt = "%1.2g%s"
205         elif value < 100:
206             fmt = "%.1f%s"
207         elif value < 1000:
208             fmt = "%d%s"
209         elif value < 1e6:
210             fmt = "%.2fk%s"; scaling = 1e3
211         elif value < 1e9:
212             fmt = "%.2fM%s"; scaling = 1e6
213         elif value < 1e12:
214             fmt = "%.2fG%s"; scaling = 1e9
215         elif value < 1e15:
216             fmt = "%.2fT%s"; scaling = 1e12
217         elif value < 1e18:
218             fmt = "%.2fP%s"; scaling = 1e15
219         else:
220             fmt = "huge! %g%s"
221         return fmt % (value / scaling, suffix)
222
223     def tearDown(self, res):
224         d = self.base_service.stopService()
225         d.addCallback(lambda ignored: res)
226         return d
227
228
229 if __name__ == '__main__':
230     test_client_dir = sys.argv[1]
231     st = SpeedTest(test_client_dir)
232     st.run()