]> granicus.if.org Git - clang/commitdiff
Introduces --stats-only option to only show changes in statistics.
authorMikhail R. Gadelha <mikhail.ramalho@gmail.com>
Mon, 28 May 2018 15:40:39 +0000 (15:40 +0000)
committerMikhail R. Gadelha <mikhail.ramalho@gmail.com>
Mon, 28 May 2018 15:40:39 +0000 (15:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333375 91177308-0d34-0410-b5e6-96231b3b80d8

utils/analyzer/CmpRuns.py

index 918e9a9f79b72b0944f412424f14c6031c9e367c..17d50ab65930c3072a6f1f12afb3d03005ff075f 100755 (executable)
@@ -26,12 +26,25 @@ Usage:
 
 """
 
-import sys
-import os
-import plistlib
+from collections import defaultdict
+
 from math import log
 from optparse import OptionParser
+import json
+import os
+import plistlib
+import re
+import sys
+
+STATS_REGEXP = re.compile(r"Statistics: (\{.+\})", re.MULTILINE | re.DOTALL)
 
+class Colors:
+    """
+    Color for terminal highlight.
+    """
+    RED = '\x1b[2;30;41m'
+    GREEN = '\x1b[6;30;42m'
+    CLEAR = '\x1b[0m'
 
 # Information about analysis run:
 # path - the analysis output directory
@@ -120,12 +133,16 @@ class AnalysisRun:
         # Cumulative list of all diagnostics from all the reports.
         self.diagnostics = []
         self.clang_version = None
+        self.stats = []
 
     def getClangVersion(self):
         return self.clang_version
 
     def readSingleFile(self, p, deleteEmpty):
         data = plistlib.readPlist(p)
+        if 'statistics' in data:
+            self.stats.append(json.loads(data['statistics']))
+            data.pop('statistics')
 
         # We want to retrieve the clang version even if there are no
         # reports. Assume that all reports were created using the same
@@ -264,12 +281,53 @@ def compareResults(A, B, opts):
 
     return res
 
+def deriveStats(results):
+    # Assume all keys are the same in each statistics bucket.
+    combined_data = defaultdict(list)
+    for stat in results.stats:
+        for key, value in stat.iteritems():
+            combined_data[key].append(value)
+    combined_stats = {}
+    for key, values in combined_data.iteritems():
+        combined_stats[str(key)] = {
+            "max": max(values),
+            "min": min(values),
+            "mean": sum(values) / len(values),
+            "median": sorted(values)[len(values) / 2],
+            "total": sum(values)
+        }
+    return combined_stats
+
+
+def compareStats(resultsA, resultsB):
+    statsA = deriveStats(resultsA)
+    statsB = deriveStats(resultsB)
+    keys = sorted(statsA.keys())
+    for key in keys:
+        print key
+        for kkey in statsA[key]:
+            valA = float(statsA[key][kkey])
+            valB = float(statsB[key][kkey])
+            report = "%.3f -> %.3f" % (valA, valB)
+            # Only apply highlighting when writing to TTY and it's not Windows
+            if sys.stdout.isatty() and os.name != 'nt':
+                if valA != 0:
+                  ratio = (valB - valA) / valB
+                  if ratio < -0.2:
+                      report = Colors.GREEN + report + Colors.CLEAR
+                  elif ratio > 0.2:
+                      report = Colors.RED + report + Colors.CLEAR
+            print "\t %s %s" % (kkey, report)
 
 def dumpScanBuildResultsDiff(dirA, dirB, opts, deleteEmpty=True,
                              Stdout=sys.stdout):
     # Load the run results.
     resultsA = loadResults(dirA, opts, opts.rootA, deleteEmpty)
     resultsB = loadResults(dirB, opts, opts.rootB, deleteEmpty)
+    if resultsA.stats:
+        compareStats(resultsA, resultsB)
+    if opts.stats_only:
+        return
 
     # Open the verbose log, if given.
     if opts.verboseLog:
@@ -339,6 +397,8 @@ def generate_option_parser():
                       default=False,
                       help="Show histogram of absolute paths differences. \
                             Requires matplotlib")
+    parser.add_option("--stats-only", action="store_true", dest="stats_only",
+                      default=False, help="Only show statistics on reports")
     return parser