Ticket #1166: rate-computation-refactoring.dpatch

File rate-computation-refactoring.dpatch, 7.3 KB (added by francois, at 2010-08-14T10:27:58Z)
Line 
1Sat Aug 14 12:04:25 CEST 2010  francois@ctrlaltdel.ch
2  * web: refactor rate computation, fixes #1166
3
4New patches:
5
6[web: refactor rate computation, fixes #1166
7francois@ctrlaltdel.ch**20100814100425
8 Ignore-this: d9a47e9b81b79c70ee8dca273627d10a
9] {
10hunk ./src/allmydata/test/test_web.py 90
11     ds.add_segment_request(2, now+4)
12     ds.add_segment_request(3, now+5)
13 
14+    # simulate a segment which gets delivered faster than a system clock tick (ticket #1166)
15+    ds.add_segment_request(4, now)
16+    ds.add_segment_delivery(4, now, 0, 140, 0.5)
17+
18     e = ds.add_dyhb_sent("serverid_a", now)
19     e.finished([1,2], now+1)
20     e = ds.add_dyhb_sent("serverid_b", now+2) # left unfinished
21hunk ./src/allmydata/test/test_web.py 3176
22         self.failUnlessReallyEqual(common.abbreviate_time(0.000123), "123us")
23         self.failUnlessReallyEqual(common.abbreviate_time(-123000), "-123000000000us")
24 
25+    def test_compute_rate(self):
26+        self.failUnlessReallyEqual(common.compute_rate(None, None), None)
27+        self.failUnlessReallyEqual(common.compute_rate(None, 1), None)
28+        self.failUnlessReallyEqual(common.compute_rate(250000, None), None)
29+        self.failUnlessReallyEqual(common.compute_rate(250000, 0), None)
30+        self.failUnlessReallyEqual(common.compute_rate(250000, 10), 2500.0)
31+        self.failUnlessReallyEqual(common.compute_rate(0, 10), 0.0)
32+        self.shouldFail(AssertionError, "test_compute_rate", "",
33+                        common.compute_rate, -100, 10)
34+        self.shouldFail(AssertionError, "test_compute_rate", "",
35+                        common.compute_rate, 100, -10)
36+
37+                   
38     def test_abbreviate_rate(self):
39         self.failUnlessReallyEqual(common.abbreviate_rate(None), "")
40         self.failUnlessReallyEqual(common.abbreviate_rate(1234000), "1.23MBps")
41hunk ./src/allmydata/web/common.py 93
42         return "%.1fms" % (1000*s)
43     return "%.0fus" % (1000000*s)
44 
45+def compute_rate(bytes, seconds):
46+    if bytes is None:
47+      return None
48+
49+    if seconds is None or seconds == 0:
50+      return None
51+
52+    # negative values don't make sense here
53+    assert bytes > -1
54+    assert seconds > 0
55+
56+    return 0.1 * bytes / seconds
57+
58 def abbreviate_rate(data):
59     # 21.8kBps, 554.4kBps 4.37MBps
60     if data is None:
61hunk ./src/allmydata/web/status.py 8
62 from nevow import rend, inevow, tags as T
63 from allmydata.util import base32, idlib
64 from allmydata.web.common import getxmlfile, get_arg, \
65-     abbreviate_time, abbreviate_rate, abbreviate_size, plural
66+     abbreviate_time, abbreviate_rate, abbreviate_size, plural, compute_rate
67 from allmydata.interfaces import IUploadStatus, IDownloadStatus, \
68      IPublishStatus, IRetrieveStatus, IServermapUpdaterStatus
69 
70hunk ./src/allmydata/web/status.py 113
71         def _convert(r):
72             file_size = r.file_size
73             time = r.timings.get(name)
74-            if time is None:
75-                return None
76-            try:
77-                return 1.0 * file_size / time
78-            except ZeroDivisionError:
79-                return None
80+            return compute_rate(file_size, time)
81         d.addCallback(_convert)
82         return d
83 
84hunk ./src/allmydata/web/status.py 135
85             file_size = r.file_size
86             time1 = r.timings.get("cumulative_encoding")
87             time2 = r.timings.get("cumulative_sending")
88-            if (file_size is None or time1 is None or time2 is None):
89-                return None
90-            try:
91-                return 1.0 * file_size / (time1+time2)
92-            except ZeroDivisionError:
93+            if (time1 is None or time2 is None):
94                 return None
95hunk ./src/allmydata/web/status.py 137
96+            else:
97+                return compute_rate(file_size, time1+time2)
98         d.addCallback(_convert)
99         return d
100 
101hunk ./src/allmydata/web/status.py 147
102         def _convert(r):
103             fetch_size = r.ciphertext_fetched
104             time = r.timings.get("cumulative_fetch")
105-            if (fetch_size is None or time is None):
106-                return None
107-            try:
108-                return 1.0 * fetch_size / time
109-            except ZeroDivisionError:
110-                return None
111+            return compute_rate(fetch_size, time)
112         d.addCallback(_convert)
113         return d
114 
115hunk ./src/allmydata/web/status.py 299
116         def _convert(r):
117             file_size = r.file_size
118             time = r.timings.get(name)
119-            if time is None:
120-                return None
121-            try:
122-                return 1.0 * file_size / time
123-            except ZeroDivisionError:
124-                return None
125+            return compute_rate(file_size, time)
126         d.addCallback(_convert)
127         return d
128 
129hunk ./src/allmydata/web/status.py 419
130             (start, length, requesttime, finishtime, bytes, decrypt, paused) = r_ev
131             if finishtime is not None:
132                 rtt = finishtime - requesttime - paused
133-                speed = self.render_rate(None, 1.0 * bytes / rtt)
134+                speed = self.render_rate(None, compute_rate(bytes, rtt))
135                 rtt = self.render_time(None, rtt)
136                 decrypt = self.render_time(None, decrypt)
137                 paused = self.render_time(None, paused)
138hunk ./src/allmydata/web/status.py 445
139             elif etype == "delivery":
140                 if reqtime[0] == segnum:
141                     segtime = when - reqtime[1]
142-                    speed = self.render_rate(None, 1.0 * seglen / segtime)
143+                    speed = self.render_rate(None, compute_rate(seglen, segtime))
144                     segtime = self.render_time(None, segtime)
145                 else:
146                     segtime, speed = "", ""
147hunk ./src/allmydata/web/status.py 581
148     def _get_rate(self, data, name):
149         file_size = self.retrieve_status.get_size()
150         time = self.retrieve_status.timings.get(name)
151-        if time is None or file_size is None:
152-            return None
153-        try:
154-            return 1.0 * file_size / time
155-        except ZeroDivisionError:
156-            return None
157+        return compute_rate(file_size, time)
158 
159     def data_time_total(self, ctx, data):
160         return self.retrieve_status.timings.get("total")
161hunk ./src/allmydata/web/status.py 682
162     def _get_rate(self, data, name):
163         file_size = self.publish_status.get_size()
164         time = self.publish_status.timings.get(name)
165-        if time is None:
166-            return None
167-        try:
168-            return 1.0 * file_size / time
169-        except ZeroDivisionError:
170-            return None
171+        return compute_rate(file_size, time)
172 
173     def data_time_total(self, ctx, data):
174         return self.publish_status.timings.get("total")
175}
176
177Context:
178
179[docs: doc of the download status page
180zooko@zooko.com**20100814054117
181 Ignore-this: a82ec33da3c39a7c0d47a7a6b5f81bbb
182 ref: http://tahoe-lafs.org/trac/tahoe-lafs/ticket/1169#comment:1
183] 
184[docs: NEWS: edit English usage, remove ticket numbers for regressions vs. 1.7.1 that were fixed again before 1.8.0c2
185zooko@zooko.com**20100811071758
186 Ignore-this: 993f5a1e6a9535f5b7a0bd77b93b66d0
187] 
188[docs: NEWS: more detail about new-downloader
189zooko@zooko.com**20100811071303
190 Ignore-this: 9f07da4dce9d794ce165aae287f29a1e
191] 
192[TAG allmydata-tahoe-1.8.0c2
193david-sarah@jacaranda.org**20100810073847
194 Ignore-this: c37f732b0e45f9ebfdc2f29c0899aeec
195] 
196Patch bundle hash:
197007b9adc44128641507932e636472f80850916d6