1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/merge-profiles.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,88 @@ 1.4 +#!/usr/bin/env python 1.5 +# 1.6 +# This script takes b2g process profiles and merged them into a single profile. 1.7 +# The meta data is taken from the first profile. The startTime for each profile 1.8 +# is used to syncronized the samples. Each thread is moved into the merged 1.9 +# profile. 1.10 +# 1.11 +import json 1.12 +import re 1.13 +import sys 1.14 + 1.15 +def MergeProfiles(files): 1.16 + threads = [] 1.17 + fileData = [] 1.18 + symTable = dict() 1.19 + meta = None 1.20 + libs = None 1.21 + minStartTime = None 1.22 + 1.23 + for fname in files: 1.24 + match = re.match('profile_([0-9]+)_(.+)\.sym', fname) 1.25 + if match is None: 1.26 + raise Exception("Filename '" + fname + "' doesn't match expected pattern") 1.27 + pid = match.groups(0)[0] 1.28 + pname = match.groups(0)[1] 1.29 + 1.30 + fp = open(fname, "r") 1.31 + fileData = json.load(fp) 1.32 + fp.close() 1.33 + 1.34 + if meta is None: 1.35 + meta = fileData['profileJSON']['meta'].copy() 1.36 + libs = fileData['profileJSON']['libs'] 1.37 + minStartTime = meta['startTime'] 1.38 + else: 1.39 + minStartTime = min(minStartTime, fileData['profileJSON']['meta']['startTime']) 1.40 + meta['startTime'] = minStartTime 1.41 + 1.42 + for thread in fileData['profileJSON']['threads']: 1.43 + thread['name'] = thread['name'] + " (" + pname + ":" + pid + ")" 1.44 + threads.append(thread) 1.45 + 1.46 + # Note that pid + sym, pid + location could be ambigious 1.47 + # if we had pid=11 sym=1 && pid=1 sym=11. 1.48 + pidStr = pid + ":" 1.49 + 1.50 + thread['startTime'] = fileData['profileJSON']['meta']['startTime'] 1.51 + samples = thread['samples'] 1.52 + for sample in thread['samples']: 1.53 + for frame in sample['frames']: 1.54 + if "location" in frame and frame['location'][0:2] == '0x': 1.55 + oldLoc = frame['location'] 1.56 + newLoc = pidStr + oldLoc 1.57 + frame['location'] = newLoc 1.58 + # Default to the unprefixed symbol if no translation is available 1.59 + symTable[newLoc] = oldLoc 1.60 + 1.61 + filesyms = fileData['symbolicationTable'] 1.62 + for sym in filesyms.keys(): 1.63 + symTable[pidStr + sym] = filesyms[sym] 1.64 + 1.65 + # For each thread, make the time offsets line up based on the 1.66 + # earliest start 1.67 + for thread in threads: 1.68 + delta = thread['startTime'] - minStartTime 1.69 + for sample in thread['samples']: 1.70 + if "time" in sample: 1.71 + sample['time'] += delta 1.72 + 1.73 + result = dict() 1.74 + result['profileJSON'] = dict() 1.75 + result['profileJSON']['meta'] = meta 1.76 + result['profileJSON']['libs'] = libs 1.77 + result['profileJSON']['threads'] = threads 1.78 + result['symbolicationTable'] = symTable 1.79 + result['format'] = "profileJSONWithSymbolicationTable,1" 1.80 + 1.81 + json.dump(result, sys.stdout) 1.82 + 1.83 + 1.84 +if len(sys.argv) > 1: 1.85 + MergeProfiles(sys.argv[1:]) 1.86 + sys.exit(0) 1.87 + 1.88 +print "Usage: merge-profile.py profile_<pid1>_<pname1>.sym profile_<pid2>_<pname2>.sym > merged.sym" 1.89 + 1.90 + 1.91 +