tools/profiler/merge-profiles.py

changeset 0
6474c204b198
     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 +

mercurial