summaryrefslogtreecommitdiff
path: root/api_profiler.py
diff options
context:
space:
mode:
Diffstat (limited to 'api_profiler.py')
-rwxr-xr-xapi_profiler.py117
1 files changed, 117 insertions, 0 deletions
diff --git a/api_profiler.py b/api_profiler.py
new file mode 100755
index 0000000..424de69
--- /dev/null
+++ b/api_profiler.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 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.
+#
+
+"""
+ This script is part of controlling simpleperf recording in user code. It is used to prepare
+ profiling environment (upload simpleperf to device and enable profiling) before recording
+ and collect recording data on host after recording.
+ Controlling simpleperf recording is done in below steps:
+ 1. Add simpleperf Java API/C++ API to the app's source code. And call the API in user code.
+ 2. Run `api_profiler.py prepare` to prepare profiling environment.
+ 3. Run the app one or more times to generate recording data.
+ 4. Run `api_profiler.py collect` to collect recording data on host.
+"""
+
+from __future__ import print_function
+import argparse
+import os
+import os.path
+import shutil
+import zipfile
+
+from utils import AdbHelper, get_target_binary_path, log_exit, log_info, remove
+
+def prepare_recording(args):
+ adb = AdbHelper()
+ enable_profiling_on_device(adb, args)
+ upload_simpleperf_to_device(adb)
+ run_simpleperf_prepare_cmd(adb)
+
+def enable_profiling_on_device(adb, args):
+ android_version = adb.get_android_version()
+ if android_version >= 10:
+ adb.set_property('debug.perf_event_max_sample_rate', str(args.max_sample_rate[0]))
+ adb.set_property('debug.perf_cpu_time_max_percent', str(args.max_cpu_percent[0]))
+ adb.set_property('debug.perf_event_mlock_kb', str(args.max_memory_in_kb[0]))
+ adb.set_property('security.perf_harden', '0')
+
+def upload_simpleperf_to_device(adb):
+ device_arch = adb.get_device_arch()
+ simpleperf_binary = get_target_binary_path(device_arch, 'simpleperf')
+ adb.check_run(['push', simpleperf_binary, '/data/local/tmp'])
+ adb.check_run(['shell', 'chmod', 'a+x', '/data/local/tmp/simpleperf'])
+
+def run_simpleperf_prepare_cmd(adb):
+ adb.check_run(['shell', '/data/local/tmp/simpleperf', 'api-prepare'])
+
+
+def collect_data(args):
+ adb = AdbHelper()
+ if not os.path.isdir(args.out_dir):
+ os.makedirs(args.out_dir)
+ download_recording_data(adb, args)
+ unzip_recording_data(args)
+
+def download_recording_data(adb, args):
+ """ download recording data to simpleperf_data.zip."""
+ upload_simpleperf_to_device(adb)
+ adb.check_run(['shell', '/data/local/tmp/simpleperf', 'api-collect', '--app', args.app[0],
+ '-o', '/data/local/tmp/simpleperf_data.zip'])
+ adb.check_run(['pull', '/data/local/tmp/simpleperf_data.zip', args.out_dir])
+ adb.check_run(['shell', 'rm', '-rf', '/data/local/tmp/simpleperf_data'])
+
+def unzip_recording_data(args):
+ zip_file_path = os.path.join(args.out_dir, 'simpleperf_data.zip')
+ with zipfile.ZipFile(zip_file_path, 'r') as zip_fh:
+ names = zip_fh.namelist()
+ log_info('There are %d recording data files.' % len(names))
+ for name in names:
+ log_info('recording file: %s' % os.path.join(args.out_dir, name))
+ zip_fh.extract(name, args.out_dir)
+ remove(zip_file_path)
+
+class ArgumentHelpFormatter(argparse.ArgumentDefaultsHelpFormatter,
+ argparse.RawDescriptionHelpFormatter):
+ pass
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__,
+ formatter_class=ArgumentHelpFormatter)
+ subparsers = parser.add_subparsers()
+ prepare_parser = subparsers.add_parser('prepare', help='Prepare recording on device.',
+ formatter_class=ArgumentHelpFormatter)
+ prepare_parser.add_argument('--max-sample-rate', nargs=1, type=int, default=[100000], help="""
+ Set max sample rate (only on Android >= Q).""")
+ prepare_parser.add_argument('--max-cpu-percent', nargs=1, type=int, default=[25], help="""
+ Set max cpu percent for recording (only on Android >= Q).""")
+ prepare_parser.add_argument('--max-memory-in-kb', nargs=1, type=int,
+ default=[(1024 + 1) * 4 * 8], help="""
+ Set max kernel buffer size for recording (only on Android >= Q).
+ """)
+ prepare_parser.set_defaults(func=prepare_recording)
+ collect_parser = subparsers.add_parser('collect', help='Collect recording data.',
+ formatter_class=ArgumentHelpFormatter)
+ collect_parser.add_argument('-p', '--app', nargs=1, required=True, help="""
+ The app package name of the app profiled.""")
+ collect_parser.add_argument('-o', '--out-dir', default='simpleperf_data', help="""
+ The directory to store recording data.""")
+ collect_parser.set_defaults(func=collect_data)
+ args = parser.parse_args()
+ args.func(args)
+
+if __name__ == '__main__':
+ main()