[Checkins] SVN: Zope/trunk/src/Products/ZCatalog/plan.py Use some named tuples to avoid hard to understand v[2][1][0] constructs

Hanno Schlichting hannosch at hannosch.eu
Sun Aug 1 17:24:15 EDT 2010


Log message for revision 115354:
  Use some named tuples to avoid hard to understand v[2][1][0] constructs
  

Changed:
  U   Zope/trunk/src/Products/ZCatalog/plan.py

-=-
Modified: Zope/trunk/src/Products/ZCatalog/plan.py
===================================================================
--- Zope/trunk/src/Products/ZCatalog/plan.py	2010-08-01 20:49:28 UTC (rev 115353)
+++ Zope/trunk/src/Products/ZCatalog/plan.py	2010-08-01 21:24:15 UTC (rev 115354)
@@ -12,6 +12,7 @@
 ##############################################################################
 
 import time
+from collections import namedtuple
 from thread import allocate_lock
 
 from Acquisition import aq_base
@@ -105,6 +106,12 @@
     return key
 
 
+Duration = namedtuple('Duration', ['start', 'end'])
+IndexMeasurement = namedtuple('IndexMeasurement',
+                              ['name', 'duration', 'num'])
+Benchmark = namedtuple('Benchmark', ['num', 'duration', 'hits'])
+
+
 class CatalogPlan(object):
     """Catalog plan class to measure and identify catalog queries and plan
     their execution.
@@ -153,42 +160,44 @@
         if not benchmark:
             return None
 
-        # sort indexes on (mean hits, mean search time)
-        ranking = [((v[0], v[1]), k) for k, v in benchmark.items()]
+        # sort indexes on (mean result length, mean search time)
+        ranking = [((value.num, value.duration), name)
+                   for name, value in benchmark.items()]
         ranking.sort()
-        return [i[1] for i in ranking]
+        return [r[1] for r in ranking]
 
     def start(self):
         self.init_timer()
         self.start_time = time.time()
 
-    def start_split(self, label, result=None):
-        self.interim[label] = (time.time(), None)
+    def start_split(self, name, result=None):
+        self.interim[name] = Duration(time.time(), None)
 
     def stop_split(self, name, result=None):
         current = time.time()
-        start_time, stop_time = self.interim.get(name, (None, None))
+        start_time, stop_time = self.interim.get(name, Duration(None, None))
         length = 0
         if result is not None:
             # TODO: calculating the length can be expensive
             length = len(result)
-        self.interim[name] = (start_time, current)
+        self.interim[name] = Duration(start_time, current)
         dt = current - start_time
-        self.res.append((name, current - start_time, length))
+        self.res.append(IndexMeasurement(
+            name=name, duration=current - start_time, num=length))
 
         # remember index's hits, search time and calls
         benchmark = self.benchmark()
         if name not in benchmark:
-            benchmark[name] = (length, dt, 1)
+            benchmark[name] = Benchmark(num=length, duration=dt, hits=1)
         else:
-            n, t, c = benchmark[name]
-            n = int(((n*c) + length) / float(c + 1))
-            t = ((t*c) + dt) / float(c + 1)
+            num, duration, hits = benchmark[name]
+            num = int(((num * hits) + length) / float(hits + 1))
+            duration = ((duration * hits) + dt) / float(hits + 1)
             # reset adaption
-            if c % REFRESH_RATE == 0:
-                c = 0
-            c += 1
-            benchmark[name] = (n, t, c)
+            if hits % REFRESH_RATE == 0:
+                hits = 0
+            hits += 1
+            benchmark[name] = Benchmark(num, duration, hits)
 
     def stop(self):
         self.end_time = time.time()
@@ -206,25 +215,24 @@
 
         if key not in stats:
             mt = self.duration
-            c = 1
+            hits = 1
         else:
-            mt, c = stats[key]
-            mt = ((mt * c) + self.duration) / float(c + 1)
-            c += 1
+            mt, hits = stats[key]
+            mt = ((mt * hits) + self.duration) / float(hits + 1)
+            hits += 1
 
-        stats[key] = (mt, c)
+        stats[key] = (mt, hits)
         self.log()
 
-    def result(self):
-        return (self.duration, tuple(self.res))
-
     def log(self):
         # result of stopwatch
-        res = self.result()
-        if res[0] < self.threshold:
+        total = self.duration
+        if total < self.threshold:
             return
 
         key = self.key
+        res = (total, self.res)
+
         reports_lock.acquire()
         try:
             if self.cid not in reports:
@@ -233,11 +241,10 @@
             previous = reports[self.cid].get(key)
             if previous:
                 counter, mean, last = previous
-                mean = (mean * counter + res[0]) / float(counter + 1)
+                mean = (mean * counter + total) / float(counter + 1)
                 reports[self.cid][key] = (counter + 1, mean, res)
             else:
-                reports[self.cid][key] = (1, res[0], res)
-
+                reports[self.cid][key] = (1, total, res)
         finally:
             reports_lock.release()
 
@@ -264,13 +271,6 @@
                                       'details': <duration of single indexes>,
                                      }
 
-        <duration of single indexes> := [{'id': <index_name1>,
-                                          'duration': <duration>,
-                                          'length': <resultset length>,
-                                         },
-                                         ...
-                                        ]
-
         The duration is provided in millisecond.
         """
         rval = []
@@ -280,9 +280,9 @@
                 'counter': v[0],
                 'duration': v[1] * 1000,
                 'last': {'duration': v[2][0] * 1000,
-                         'details': [dict(id=i[0],
-                                          duration=i[1]*1000,
-                                          length=i[2])
+                         'details': [dict(id=i.name,
+                                          duration=i.duration * 1000,
+                                          length=i.num)
                                      for i in v[2][1]],
                         },
                 }



More information about the checkins mailing list