[tor-commits] [sbws/master] Move functions to methods

juga at torproject.org juga at torproject.org
Tue Sep 18 09:26:11 UTC 2018


commit a98787cface97bb7e248e2e4a98123d5425ef9dd
Author: juga0 <juga at riseup.net>
Date:   Wed Aug 29 17:35:23 2018 +0000

    Move functions to methods
---
 sbws/lib/v3bwfile.py | 93 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 34 deletions(-)

diff --git a/sbws/lib/v3bwfile.py b/sbws/lib/v3bwfile.py
index ef9eadc..42e318c 100644
--- a/sbws/lib/v3bwfile.py
+++ b/sbws/lib/v3bwfile.py
@@ -2,12 +2,13 @@
 """Classes and functions that create the bandwidth measurements document
 (v3bw) used by bandwidth authorities."""
 
+import copy
 import logging
 import os
-from statistics import median
+from statistics import median, mean
 
 from sbws import __version__
-from sbws.globals import SPEC_VERSION, BW_LINE_SIZE
+from sbws.globals import SPEC_VERSION, BW_LINE_SIZE, SCALE_CONSTANT
 from sbws.lib.resultdump import ResultSuccess, _ResultType
 from sbws.util.filelock import DirectoryLock
 from sbws.util.timestamp import now_isodt_str, unixts_to_isodt_str
@@ -40,33 +41,6 @@ BW_KEYVALUES_INT = ['bw', 'rtt', 'success', 'error_stream',
 BW_KEYVALUES = ['node_id', 'bw'] + BW_EXTRA_ARG_KEYVALUES
 
 
-def total_bw(bw_lines):
-    return sum([l.bw for l in bw_lines])
-
-
-def avg_bw(bw_lines):
-    assert len(bw_lines) > 0
-    return total_bw(bw_lines) / len(bw_lines)
-
-
-def scale_lines(bw_lines, scale_constant):
-    avg = avg_bw(bw_lines)
-    for line in bw_lines:
-        line.bw = round(line.bw / avg * scale_constant)
-    warn_if_not_accurate_enough(bw_lines, scale_constant)
-    return bw_lines
-
-
-def warn_if_not_accurate_enough(bw_lines, scale_constant):
-    margin = 0.001
-    accuracy_ratio = avg_bw(bw_lines) / scale_constant
-    log.info('The generated lines are within {:.5}% of what they should '
-             'be'.format((1 - accuracy_ratio) * 100))
-    if accuracy_ratio < 1 - margin or accuracy_ratio > 1 + margin:
-        log.warning('There was %f%% error and only +/- %f%% is '
-                    'allowed', (1 - accuracy_ratio) * 100, margin * 100)
-
-
 def num_results_of_type(results, type_str):
     return len([r for r in results if r.type == type_str])
 
@@ -387,17 +361,68 @@ class V3BWFile(object):
         f = cls(header, bw_lines)
         return f
 
+    @staticmethod
+    def bw_sbws_scale(bw_lines, scale_constant=SCALE_CONSTANT,
+                      reverse=False):
+        """Return a new V3BwLine list scaled using sbws method.
+
+        :param list bw_lines:
+            bw lines to scale, not self.bw_lines,
+            since this method will be before self.bw_lines have been
+            initialized.
+        :param int scale_constant:
+            the constant to multiply by the ratio and
+            the bandwidth to obtain the new bandwidth
+        :returns list: V3BwLine list
+        """
+        # If a relay has MaxAdvertisedBandwidth set, they may be capable of
+        # some large amount of bandwidth but prefer if they didn't receive it.
+        # We also could have managed to measure them faster than their
+        # {,Relay}BandwidthRate somehow.
+        #
+        # See https://github.com/pastly/simple-bw-scanner/issues/155 and
+        # https://trac.torproject.org/projects/tor/ticket/8494
+        #
+        # Note how this isn't some measured-by-us average of bandwidth. It's
+        # the first value on the 'bandwidth' line in the relay's server
+        # descriptor.
+        log.debug('Scaling bandwidth using sbws method.')
+        m = median([l.bw for l in bw_lines])
+        bw_lines_scaled = copy.deepcopy(bw_lines)
+        for l in bw_lines_scaled:
+            # min is to limit the bw to descriptor average-bandwidth
+            # max to avoid bandwidth with 0 value
+            l.bw = max(round(min(l.desc_avg_bw_bs,
+                                 l.bw_bs_median * scale_constant / m)
+                             / 1000), 1)
+        return sorted(bw_lines_scaled, key=lambda x: x.bw, reverse=reverse)
+
+    @staticmethod
+    def warn_if_not_accurate_enough(bw_lines,
+                                    scale_constant=SCALE_CONSTANT):
+        margin = 0.001
+        accuracy_ratio = median([l.bw for l in bw_lines]) / scale_constant
+        log.info('The generated lines are within {:.5}% of what they should '
+                 'be'.format((1 - accuracy_ratio) * 100))
+        if accuracy_ratio < 1 - margin or accuracy_ratio > 1 + margin:
+            log.warning('There was %f%% error and only +/- %f%% is '
+                        'allowed', (1 - accuracy_ratio) * 100, margin * 100)
+
     @property
-    def total_bw(self):
-        return total_bw(self.bw_lines)
+    def sum_bw(self):
+        return sum([l.bw for l in self.bw_lines])
 
     @property
-    def num_lines(self):
+    def num(self):
         return len(self.bw_lines)
 
     @property
-    def avg_bw(self):
-        return self.total_bw / self.num_lines
+    def mean_bw(self):
+        return mean([l.bw for l in self.bw_lines])
+
+    @property
+    def median_bw(self):
+        return median([l.bw for l in self.bw_lines])
 
     def write(self, output):
         if output == '/dev/stdout':





More information about the tor-commits mailing list