1 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 6 """A helper module for parsing JSON objects from perf tests results.""" 7 8 import json 9 10 11 def GetAverageRunInfo(json_data, name): 12 """Summarizes TraceEvent JSON data for performance metrics. 13 14 Example JSON Inputs (More tags can be added but these are required): 15 Measuring Duration: 16 [ 17 { "cat": "Java", 18 "ts": 10000000000, 19 "ph": "S", 20 "name": "TestTrace" 21 }, 22 { "cat": "Java", 23 "ts": 10000004000, 24 "ph": "F", 25 "name": "TestTrace" 26 }, 27 ... 28 ] 29 30 Measuring Call Frequency (FPS): 31 [ 32 { "cat": "Java", 33 "ts": 10000000000, 34 "ph": "I", 35 "name": "TestTraceFPS" 36 }, 37 { "cat": "Java", 38 "ts": 10000004000, 39 "ph": "I", 40 "name": "TestTraceFPS" 41 }, 42 ... 43 ] 44 45 Args: 46 json_data: A list of dictonaries each representing a JSON object. 47 name: The 'name' tag to filter on in the JSON file. 48 49 Returns: 50 A dictionary of result data with the following tags: 51 min: The minimum value tracked. 52 max: The maximum value tracked. 53 average: The average of all the values tracked. 54 count: The number of times the category/name pair was tracked. 55 type: The type of tracking ('Instant' for instant tags and 'Span' for 56 begin/end tags. 57 category: The passed in category filter. 58 name: The passed in name filter. 59 data_points: A list of all of the times used to generate this data. 60 units: The units for the values being reported. 61 62 Raises: 63 Exception: if entry contains invalid data. 64 """ 65 66 def EntryFilter(entry): 67 return entry['cat'] == 'Java' and entry['name'] == name 68 filtered_entries = [j for j in json_data if EntryFilter(j)] 69 70 result = {} 71 72 result['min'] = -1 73 result['max'] = -1 74 result['average'] = 0 75 result['count'] = 0 76 result['type'] = 'Unknown' 77 result['category'] = 'Java' 78 result['name'] = name 79 result['data_points'] = [] 80 result['units'] = '' 81 82 total_sum = 0 83 84 last_val = 0 85 val_type = None 86 for entry in filtered_entries: 87 if not val_type: 88 if 'mem' in entry: 89 val_type = 'mem' 90 91 def GetVal(entry): 92 return entry['mem'] 93 94 result['units'] = 'kb' 95 elif 'ts' in entry: 96 val_type = 'ts' 97 98 def GetVal(entry): 99 return float(entry['ts']) / 1000.0 100 101 result['units'] = 'ms' 102 else: 103 raise Exception('Entry did not contain valid value info: %s' % entry) 104 105 if not val_type in entry: 106 raise Exception('Entry did not contain expected value type "%s" ' 107 'information: %s' % (val_type, entry)) 108 val = GetVal(entry) 109 if (entry['ph'] == 'S' and 110 (result['type'] == 'Unknown' or result['type'] == 'Span')): 111 result['type'] = 'Span' 112 last_val = val 113 elif ((entry['ph'] == 'F' and result['type'] == 'Span') or 114 (entry['ph'] == 'I' and (result['type'] == 'Unknown' or 115 result['type'] == 'Instant'))): 116 if last_val > 0: 117 delta = val - last_val 118 if result['min'] == -1 or result['min'] > delta: 119 result['min'] = delta 120 if result['max'] == -1 or result['max'] < delta: 121 result['max'] = delta 122 total_sum += delta 123 result['count'] += 1 124 result['data_points'].append(delta) 125 if entry['ph'] == 'I': 126 result['type'] = 'Instant' 127 last_val = val 128 if result['count'] > 0: 129 result['average'] = total_sum / result['count'] 130 131 return result 132 133 134 def GetAverageRunInfoFromJSONString(json_string, name): 135 """Returns the results from GetAverageRunInfo using a JSON string. 136 137 Args: 138 json_string: The string containing JSON. 139 name: The 'name' tag to filter on in the JSON file. 140 141 Returns: 142 See GetAverageRunInfo Returns section. 143 """ 144 return GetAverageRunInfo(json.loads(json_string), name) 145 146 147 def GetAverageRunInfoFromFile(json_file, name): 148 """Returns the results from GetAverageRunInfo using a JSON file. 149 150 Args: 151 json_file: The path to a JSON file. 152 name: The 'name' tag to filter on in the JSON file. 153 154 Returns: 155 See GetAverageRunInfo Returns section. 156 """ 157 with open(json_file, 'r') as f: 158 data = f.read() 159 perf = json.loads(data) 160 161 return GetAverageRunInfo(perf, name) 162