Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ccaec63 authored by Stan Iliev's avatar Stan Iliev
Browse files

Create helper script to parse systrace files

Create a script that can parse systrace files and calculates
metrics. The example metrics are average DrawFrame and average
time to record a View.

Test: ran the script and compared outputs with numbers visible,
when systrace file is opened in a browser.

Change-Id: If37322e7838e177efb3e2e4a00cb6e97755aa453
parent 6e6f4882
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
#!/usr/bin/env python

import codecs, httplib, json, os, urllib, shutil, subprocess, sys, argparse

upstream_git = 'https://github.com/catapult-project/catapult.git'

script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
catapult_src_dir = os.path.join(script_dir, 'catapult-upstream')

parser = argparse.ArgumentParser()
parser.add_argument('trace_file_or_dir',
      help='Path to trace file or directory of trace files.')
parser.add_argument('--output_file', dest='outfile', default=os.path.join(os.getcwd(), 'mapper_output.json'),
      help='Path to output file to store results.')
parser.add_argument('--mapper_func', dest='func', default='AvgDrawFrame',
      help='Name of javascript mapper function in systrace_parser.html.')
args = parser.parse_args()

# Update the source if needed.
if not os.path.exists(catapult_src_dir):
  # Pull the latest source from the upstream git.
  git_args = ['git', 'clone', upstream_git, catapult_src_dir]
  p = subprocess.Popen(git_args, stdout=subprocess.PIPE, cwd=script_dir)
  p.communicate()
  if p.wait() != 0:
    print 'Failed to checkout source from upstream git.'
    sys.exit(1)

mapper_func_file = os.path.join(script_dir, 'systrace_parser.html')
path_to_process_traces = os.path.join(catapult_src_dir, 'trace_processor/bin/process_traces')
run_command = path_to_process_traces + " --mapper_handle " + mapper_func_file + ":" + args.func + " --output_file " + args.outfile + " " + args.trace_file_or_dir
print run_command
sys.exit(os.system(run_command))
+89 −0
Original line number Diff line number Diff line
<!DOCTYPE html>

<script>
'use strict';

const RENDER_THREAD_NAME = "RenderThread";
const UI_THREAD_NAME = "UI Thread";
const DRAW_FRAME_SLICE_TITLE = "DrawFrame";
const BINDER_SLICE_TITLE = "binder transaction";
const RECORD_SLICE_TITLE = "Record View#draw()";
const DEQUEUE_BUFFER_SLICE_TITLE = "dequeueBuffer";

function getTimeInBinder(slice) {
    if (slice.title === BINDER_SLICE_TITLE) {
        return slice.duration;
    }
    let result = 0.0;
    for (let subslice of slice.subSlices) {
        result += getTimeInBinder(subslice);
    }
    return result;
}

function getTimeInDequeueBuffer(slice) {
    if (slice.title === DEQUEUE_BUFFER_SLICE_TITLE) {
        return slice.duration;
    }
    let result = 0.0;
    for (let subslice of slice.subSlices) {
        result += getTimeInDequeueBuffer(subslice);
    }
    return result;
}

tr.mre.FunctionRegistry.register(
    function AvgDrawFrame(result, model) {
        let canonicalUrl = model.canonicalUrl;

        for (let p of model.getAllProcesses()) {
            //calc stats for processes that have UI and render threads and at least 10 frames
            let renderThread = p.findAtMostOneThreadNamed(RENDER_THREAD_NAME);
            let UIThread = p.findAtMostOneThreadNamed(UI_THREAD_NAME);
            if (renderThread && UIThread)
            {
                let numDrawFrames = 0;
                let drawFramesWallDuration = 0.0;
                let binderDuration = 0.0;
                let dequeueBufferDuration = 0.0;

                let numRecordViewDraw = 0;
                let recordViewDrawWallDuration = 0.0;

                renderThread.sliceGroup.slices.forEach(function(slice) {
                    if (slice.title === DRAW_FRAME_SLICE_TITLE) {
                        drawFramesWallDuration += slice.duration;
                        numDrawFrames++;
                        binderDuration += getTimeInBinder(slice);
                        dequeueBufferDuration += getTimeInDequeueBuffer(slice);
                    }
                });
                if (numDrawFrames < 10) continue;
                UIThread.sliceGroup.slices.forEach(function(slice) {
                    if (slice.title === RECORD_SLICE_TITLE) {
                        recordViewDrawWallDuration += slice.duration;
                        numRecordViewDraw++;
                    }
                });

                let avgDrawFrameDuration = undefined;
                if (numDrawFrames > 0) {
                    avgDrawFrameDuration = (drawFramesWallDuration-dequeueBufferDuration)/numDrawFrames;
                }
                let avgRecordViewDrawDuration = undefined;
                if (numRecordViewDraw > 0) {
                    avgRecordViewDrawDuration = recordViewDrawWallDuration/numRecordViewDraw;
                }

                result.addPair('result', {
                    canonicalUrl: canonicalUrl,
                    processName: p.name,
                    avgDrawFrameDuration: Number(avgDrawFrameDuration).toFixed(3),
                    avgRecordViewDrawDuration: Number(avgRecordViewDrawDuration).toFixed(3),
                    avgRecordAndPlay: Number(avgDrawFrameDuration+avgRecordViewDrawDuration).toFixed(3)
                });
            }
        }
    });

</script>