json_perf_parser.py revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""A helper module for parsing JSON objects from perf tests results.""" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import json 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetAverageRunInfo(json_data, name): 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Summarizes TraceEvent JSON data for performance metrics. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Example JSON Inputs (More tags can be added but these are required): 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Measuring Duration: 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [ 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "cat": "Java", 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ts": 10000000000, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ph": "S", 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name": "TestTrace" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "cat": "Java", 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ts": 10000004000, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ph": "F", 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name": "TestTrace" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ... 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ] 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Measuring Call Frequency (FPS): 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [ 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "cat": "Java", 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ts": 10000000000, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ph": "I", 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name": "TestTraceFPS" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "cat": "Java", 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ts": 10000004000, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ph": "I", 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name": "TestTraceFPS" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ... 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ] 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_data: A list of dictonaries each representing a JSON object. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: The 'name' tag to filter on in the JSON file. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A dictionary of result data with the following tags: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min: The minimum value tracked. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max: The maximum value tracked. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) average: The average of all the values tracked. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count: The number of times the category/name pair was tracked. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type: The type of tracking ('Instant' for instant tags and 'Span' for 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) begin/end tags. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) category: The passed in category filter. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: The passed in name filter. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_points: A list of all of the times used to generate this data. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) units: The units for the values being reported. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Raises: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Exception: if entry contains invalid data. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def EntryFilter(entry): 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry['cat'] == 'Java' and entry['name'] == name 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filtered_entries = filter(EntryFilter, json_data) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = {} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['min'] = -1 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['max'] = -1 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['average'] = 0 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['count'] = 0 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['type'] = 'Unknown' 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['category'] = 'Java' 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['name'] = name 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['data_points'] = [] 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['units'] = '' 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_sum = 0 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_val = 0 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val_type = None 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for entry in filtered_entries: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not val_type: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if 'mem' in entry: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val_type = 'mem' 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetVal(entry): 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry['mem'] 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['units'] = 'kb' 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif 'ts' in entry: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val_type = 'ts' 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetVal(entry): 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return float(entry['ts']) / 1000.0 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['units'] = 'ms' 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise Exception('Entry did not contain valid value info: %s' % entry) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not val_type in entry: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise Exception('Entry did not contain expected value type "%s" ' 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'information: %s' % (val_type, entry)) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val = GetVal(entry) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry['ph'] == 'S' and 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (result['type'] == 'Unknown' or result['type'] == 'Span')): 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['type'] = 'Span' 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_val = val 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif ((entry['ph'] == 'F' and result['type'] == 'Span') or 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (entry['ph'] == 'I' and (result['type'] == 'Unknown' or 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['type'] == 'Instant'))): 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if last_val > 0: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delta = val - last_val 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if result['min'] == -1 or result['min'] > delta: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['min'] = delta 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if result['max'] == -1 or result['max'] < delta: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['max'] = delta 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_sum += delta 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['count'] += 1 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['data_points'].append(delta) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if entry['ph'] == 'I': 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result['type'] = 'Instant' 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_val = val 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if result['count'] > 0: 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result['average'] = total_sum / result['count'] 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetAverageRunInfoFromJSONString(json_string, name): 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the results from GetAverageRunInfo using a JSON string. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_string: The string containing JSON. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: The 'name' tag to filter on in the JSON file. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) See GetAverageRunInfo Returns section. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetAverageRunInfo(json.loads(json_string), name) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetAverageRunInfoFromFile(json_file, name): 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the results from GetAverageRunInfo using a JSON file. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json_file: The path to a JSON file. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: The 'name' tag to filter on in the JSON file. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) See GetAverageRunInfo Returns section. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(json_file, 'r') as f: 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data = f.read() 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perf = json.loads(data) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetAverageRunInfo(perf, name) 162