summaryrefslogtreecommitdiff
path: root/startop
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2020-02-28 15:30:51 -0800
committerIgor Murashkin <iam@google.com>2020-02-28 15:30:51 -0800
commit7ed889c071ae6967598043950e05ed460a58477b (patch)
treed7a27885537551a472d21657ab4e5aa649ce75e3 /startop
parenta52f95e589f8cc9bd684561e6679ca05015c897e (diff)
downloadbase-7ed889c071ae6967598043950e05ed460a58477b.tar.gz
iorap: Add script to analyze iorap's compiled TraceFile.
Bug: 150492328 Test: ./analyze_prefetch_file.py -i <path-to-compiled-trace-pb> Change-Id: I7ba956b34f71d43fbb3f475e618ee67fe0c67740
Diffstat (limited to 'startop')
-rwxr-xr-xstartop/scripts/iorap/analyze_prefetch_file.py168
1 files changed, 168 insertions, 0 deletions
diff --git a/startop/scripts/iorap/analyze_prefetch_file.py b/startop/scripts/iorap/analyze_prefetch_file.py
new file mode 100755
index 000000000000..343cd54b7174
--- /dev/null
+++ b/startop/scripts/iorap/analyze_prefetch_file.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import os
+import sys
+from typing import Dict, List, NamedTuple, Tuple
+
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR)) # framework/base/startop/script
+import lib.print_utils as print_utils
+
+# Include generated protos.
+dir_name = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(dir_name + "/generated")
+
+from TraceFile_pb2 import *
+
+def parse_options(argv: List[str] = None):
+ """Parses command line arguments and returns an argparse Namespace object."""
+ parser = argparse.ArgumentParser(description="Analyze compiled_trace iorap protos.")
+ required_named = parser.add_argument_group('required named arguments')
+
+ required_named.add_argument('-i', dest='input', metavar='FILE',
+ help='Read protobuf file as input')
+
+ optional_named = parser.add_argument_group('optional named arguments')
+
+ optional_named.add_argument('-up', dest='upper_percent', type=float,
+ default=95.0,
+ help='Only show the top-most entries up to this value.')
+
+ optional_named.add_argument('-r', dest='raw', action='store_true',
+ help='Output entire raw file.')
+ optional_named.add_argument('-o', dest='output',
+ help='The results are stored into the output file')
+ optional_named.add_argument('-d', dest='debug', action='store_true'
+ , help='Activity of the app to be compiled')
+
+ return parser.parse_args(argv)
+
+def open_iorap_prefetch_file(file_path: str) -> TraceFile:
+ with open(file_path, "rb") as f:
+ tf = TraceFile()
+ tf.ParseFromString(f.read())
+ return tf
+
+def print_stats_summary(trace_file: TraceFile, upper_percent):
+ tf_dict = convert_to_dict(trace_file)
+ print_utils.debug_print(tf_dict)
+
+ total_length = 0
+ summaries = []
+ for name, entries_list in tf_dict.items():
+ summary = entries_sum(entries_list)
+ summaries.append(summary)
+
+ total_length += summary.length
+
+ # Sort by length
+ summaries.sort(reverse=True, key=lambda s: s.length)
+
+ percent_sum = 0.0
+ skipped_entries = 0
+
+ print("===========================================")
+ print("Total length: {:,} bytes".format(total_length))
+ print("Displayed upper percent: {:0.2f}%".format(upper_percent))
+ print("===========================================")
+ print("")
+ print("name,length,percent_of_total,upper_percent")
+ for sum in summaries:
+ percent_of_total = (sum.length * 1.0) / (total_length * 1.0) * 100.0
+
+ percent_sum += percent_of_total
+
+ if percent_sum > upper_percent:
+ skipped_entries = skipped_entries + 1
+ continue
+
+ #print("%s,%d,%.2f%%" %(sum.name, sum.length, percent_of_total))
+ print("{:s},{:d},{:0.2f}%,{:0.2f}%".format(sum.name, sum.length, percent_of_total, percent_sum))
+
+ if skipped_entries > 0:
+ print("[WARNING] Skipped {:d} entries, use -up=100 to show everything".format(skipped_entries))
+
+ pass
+
+class FileEntry(NamedTuple):
+ id: int
+ name: str
+ offset: int
+ length: int
+
+class FileEntrySummary(NamedTuple):
+ name: str
+ length: int
+
+def entries_sum(entries: List[FileEntry]) -> FileEntrySummary:
+ if not entries:
+ return None
+
+ summary = FileEntrySummary(name=entries[0].name, length=0)
+ for entry in entries:
+ summary = FileEntrySummary(summary.name, summary.length + entry.length)
+
+ return summary
+
+def convert_to_dict(trace_file: TraceFile) -> Dict[str, FileEntry]:
+ trace_file_index = trace_file.index
+
+ # entries.id -> entry.file_name
+ entries_map = {}
+
+ index_entries = trace_file_index.entries
+ for entry in index_entries:
+ entries_map[entry.id] = entry.file_name
+
+ final_map = {}
+
+ file_entries_map = {}
+ file_entries = trace_file.list.entries
+ for entry in file_entries:
+ print_utils.debug_print(entry)
+
+ lst = file_entries_map.get(entry.index_id, [])
+ file_entries_map[entry.index_id] = lst
+
+ file_name = entries_map[entry.index_id]
+ file_entry = \
+ FileEntry(id=entry.index_id, name=file_name, offset=entry.file_offset, length=entry.file_length)
+
+ lst.append(file_entry)
+
+ final_map[file_name] = lst
+
+ return final_map
+
+def main(argv: List[str]) -> int:
+ opts = parse_options(argv[1:])
+ if opts.debug:
+ print_utils.DEBUG = opts.debug
+ print_utils.debug_print(opts)
+
+ prefetch_file = open_iorap_prefetch_file(opts.input)
+
+ if opts.raw:
+ print(prefetch_file)
+
+ print_stats_summary(prefetch_file, opts.upper_percent)
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))