1#!/usr/bin/env python3
2#
3# Copyright (C) 2023 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import gzip
18import json
19import os
20import sys
21
22from collections import defaultdict
23
24READ_DURATION = [
25    'soong',
26    'kati build',
27    'ninja',
28    'total',
29]
30
31class Trace:
32    def __init__(self, trace_file):
33        self.duration = dict()
34        self._queue = defaultdict(list)
35        self.target = os.path.splitext(os.path.basename(trace_file))[0]
36        if not os.path.isfile(trace_file):
37            return
38        self._trace_file = gzip.open(trace_file, 'rt', encoding='utf-8')
39        self._trace_data = json.load(self._trace_file)
40        for t in self._trace_data:
41            if 'ph' not in t:
42                continue
43            if t['ph'] == 'X':
44                self.duration[t['name']] = t['dur']
45                continue
46            if t['ph'] == 'B':
47                self._queue[(t['pid'], t['pid'])].append((t['name'], t['ts']))
48                continue
49            if t['ph'] == 'E':
50                queue = self._queue[(t['pid'], t['pid'])]
51                if not queue:
52                    raise Exception('pid:{}, tid:{} not started'.format(t['pid'], t['pid']))
53                name, ts = queue.pop()
54                self.duration[name] = t['ts'] - ts
55                continue
56
57    def out_durations(self):
58        out_str = self.target
59        for name in READ_DURATION:
60            if name not in self.duration:
61                continue
62            out_str = '{}, {}'.format(out_str, self.duration[name])
63        out_str += '\n'
64        sys.stdout.write(out_str)
65
66
67def main(argv):
68    trace = Trace(argv[1])
69    trace.out_durations()
70
71if __name__ == '__main__':
72    main(sys.argv)
73