1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)"""This is a helper module to get and manipulate histogram data. 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)The histogram data is the same data as is visible from "chrome://histograms". 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)More information can be found at: chromium/src/base/metrics/histogram.h 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)""" 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport collections 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import json 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BROWSER_HISTOGRAM = 'browser_histogram' 163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)RENDERER_HISTOGRAM = 'renderer_histogram' 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)def CustomizeBrowserOptions(options): 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) """Allows histogram collection.""" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) options.AppendExtraBrowserArgs(['--enable-stats-collection-bindings']) 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def SubtractHistogram(histogram_json, start_histogram_json): 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) """Subtracts a previous histogram from a histogram. 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Both parameters and the returned result are json serializations. 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) """ 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_histogram = json.loads(start_histogram_json) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # It's ok if the start histogram is empty (we had no data, maybe even no 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # histogram at all, at the start of the test). 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if 'buckets' not in start_histogram: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return histogram_json 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) histogram = json.loads(histogram_json) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('pid' in start_histogram and 'pid' in histogram 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) and start_histogram['pid'] != histogram['pid']): 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) raise Exception( 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 'Trying to compare histograms from different processes (%d and %d)' 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) % (start_histogram['pid'], histogram['pid'])) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_histogram_buckets = dict() 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for b in start_histogram['buckets']: 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_histogram_buckets[b['low']] = b['count'] 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_buckets = [] 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for b in histogram['buckets']: 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_bucket = b 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) low = b['low'] 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if low in start_histogram_buckets: 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_bucket['count'] = b['count'] - start_histogram_buckets[low] 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if new_bucket['count'] < 0: 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logging.error('Histogram subtraction error, starting histogram most ' 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'probably invalid.') 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if new_bucket['count']: 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_buckets.append(new_bucket) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram['buckets'] = new_buckets 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) histogram['count'] -= start_histogram['count'] 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return json.dumps(histogram) 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef AddHistograms(histogram_jsons): 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """Adds histograms together. Used for aggregating data. 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci The parameter is a list of json serializations and the returned result is a 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci json serialization too. 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Note that the histograms to be added together are typically from different 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci processes. 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """ 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buckets = collections.defaultdict(int) 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for histogram_json in histogram_jsons: 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci h = json.loads(histogram_json) 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for b in h['buckets']: 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci key = (b['low'], b['high']) 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buckets[key] += b['count'] 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buckets = [{'low': key[0], 'high': key[1], 'count': value} 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for key, value in buckets.iteritems()] 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buckets.sort(key = lambda h : h['low']) 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result_histogram = {} 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result_histogram['buckets'] = buckets 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return json.dumps(result_histogram) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)def GetHistogram(histogram_type, histogram_name, tab): 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) """Get a json serialization of a histogram.""" 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) assert histogram_type in [BROWSER_HISTOGRAM, RENDERER_HISTOGRAM] 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function = 'getHistogram' 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if histogram_type == BROWSER_HISTOGRAM: 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function = 'getBrowserHistogram' 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) histogram_json = tab.EvaluateJavaScript( 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 'statsCollectionController.%s("%s")' % 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (function, histogram_name)) 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if histogram_json: 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return histogram_json 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return None 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)def GetHistogramCount(histogram_type, histogram_name, tab): 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) """Get the count of events for the given histograms.""" 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) histogram_json = GetHistogram(histogram_type, histogram_name, tab) 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) histogram = json.loads(histogram_json) 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if 'count' in histogram: 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return histogram['count'] 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else: 1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def GetHistogramSum(histogram_type, histogram_name, tab): 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """Get the sum of events for the given histograms.""" 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) histogram_json = GetHistogram(histogram_type, histogram_name, tab) 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) histogram = json.loads(histogram_json) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if 'sum' in histogram: 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return histogram['sum'] 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else: 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return 0 120