diff options
author | Yabin Cui <yabinc@google.com> | 2018-04-12 22:06:10 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-04-12 22:06:10 +0000 |
commit | 0c3afce549e3d696fa7f1213457754f1cb54c528 (patch) | |
tree | d3c232e5bf66c3ddda37327fb5692ee9b2d2ecfb | |
parent | a6ee510913c53783875a5512ff0d00a26b31eaad (diff) | |
parent | d5d9c4293b3d8b659905770bb9c501c6fa8e7c6f (diff) | |
download | extras-0c3afce549e3d696fa7f1213457754f1cb54c528.tar.gz |
Merge "simpleperf: add a python script to record without usb connection."
-rw-r--r-- | simpleperf/environment.cpp | 6 | ||||
-rw-r--r-- | simpleperf/scripts/pylintrc | 8 | ||||
-rw-r--r-- | simpleperf/scripts/run_simpleperf_without_usb_connection.py | 94 | ||||
-rw-r--r-- | simpleperf/scripts/test.py | 12 |
4 files changed, 118 insertions, 2 deletions
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp index cf9167c2..9843ab0f 100644 --- a/simpleperf/environment.cpp +++ b/simpleperf/environment.cpp @@ -632,7 +632,11 @@ bool RunInAppContext(const std::string& app_package_name, const std::string& cmd IOEventLoop loop; bool need_to_kill_child = false; - if (!loop.AddSignalEvents({SIGINT, SIGTERM, SIGHUP}, + std::vector<int> stop_signals = {SIGINT, SIGTERM}; + if (!SignalIsIgnored(SIGHUP)) { + stop_signals.push_back(SIGHUP); + } + if (!loop.AddSignalEvents(stop_signals, [&]() { need_to_kill_child = true; return loop.ExitLoop(); })) { return false; } diff --git a/simpleperf/scripts/pylintrc b/simpleperf/scripts/pylintrc new file mode 100644 index 00000000..0a02cfcb --- /dev/null +++ b/simpleperf/scripts/pylintrc @@ -0,0 +1,8 @@ +[MESSAGES CONTROL] +# C0111 = Missing docstring +# W0403 = Relative imports +disable=C0111,W0403 + +[BASIC] +function-rgx=[a-z_][a-z0-9_]{2,50}$ +method-rgx=[a-z_][a-z0-9_]{2,50}$ diff --git a/simpleperf/scripts/run_simpleperf_without_usb_connection.py b/simpleperf/scripts/run_simpleperf_without_usb_connection.py new file mode 100644 index 00000000..ef529e07 --- /dev/null +++ b/simpleperf/scripts/run_simpleperf_without_usb_connection.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 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. +# + +""" + Support profiling without usb connection in below steps: + 1. With usb connection, start simpleperf recording. + 2. Unplug the usb cable and play the app you want to profile, while the process of + simpleperf keeps running and collecting samples. + 3. Replug the usb cable, stop simpleperf recording and pull recording file on host. + + Note that recording is stopped once the app is killed. So if you restart the app + during profiling time, simpleperf only records the first running. +""" + +from __future__ import print_function +import argparse +import subprocess +import sys +import time + +from utils import AdbHelper, get_target_binary_path, log_warning + +def start_recording(args): + adb = AdbHelper() + 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']) + adb.check_run(['shell', 'rm', '-rf', '/data/local/tmp/perf.data', + '/data/local/tmp/simpleperf_output']) + shell_cmd = 'cd /data/local/tmp && nohup ./simpleperf record ' + args.record_options + if args.app: + shell_cmd += ' --app ' + args.app + shell_cmd += ' >/data/local/tmp/simpleperf_output 2>&1' + print('shell_cmd: %s' % shell_cmd) + subproc = subprocess.Popen([adb.adb_path, 'shell', shell_cmd]) + # Wait 2 seconds to see if the simpleperf command fails to start. + time.sleep(2) + if subproc.poll() is None: + print('Simpleperf recording has started. Please unplug the usb cable and run the app.') + print('After that, run `%s stop` to get recording result.' % sys.argv[0]) + else: + adb.run(['shell', 'cat', '/data/local/tmp/simpleperf_output']) + sys.exit(subproc.returncode) + +def stop_recording(args): + adb = AdbHelper() + result = adb.run(['shell', 'pidof', 'simpleperf']) + if not result: + log_warning('No simpleperf process on device. The recording has ended.') + else: + adb.run(['shell', 'pkill', '-l', '2', 'simpleperf']) + print('Waiting for simpleperf process to finish...') + while adb.run(['shell', 'pidof', 'simpleperf']): + time.sleep(1) + adb.check_run(['pull', '/data/local/tmp/perf.data', args.perf_data_path]) + adb.run(['shell', 'cat', '/data/local/tmp/simpleperf_output']) + print('The recording data has been collected in %s.' % args.perf_data_path) + +def main(): + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers() + start_parser = subparsers.add_parser('start', help='Start recording.') + start_parser.add_argument('-r', '--record_options', + default='-e task-clock:u -g', + help="""Set options for `simpleperf record` command. + Default is '-e task-clock:u -g --no-post-unwind.""") + start_parser.add_argument('-p', '--app', help="""Profile an Android app, given the package + name. Like -p com.example.android.myapp.""") + start_parser.set_defaults(func=start_recording) + stop_parser = subparsers.add_parser('stop', help='Stop recording.') + stop_parser.add_argument('-o', '--perf_data_path', default='perf.data', help="""The path to + store profiling data on host. Default is perf.data.""") + stop_parser.set_defaults(func=stop_recording) + args = parser.parse_args() + args.func(args) + +if __name__ == '__main__': + main() diff --git a/simpleperf/scripts/test.py b/simpleperf/scripts/test.py index cad5d703..c7215c30 100644 --- a/simpleperf/scripts/test.py +++ b/simpleperf/scripts/test.py @@ -454,6 +454,16 @@ class TestExamplePureJava(TestExampleBase): def test_report_html(self): self.common_test_report_html() + def test_run_simpleperf_without_usb_connection(self): + self.adb.check_run(['shell', 'am', 'start', '-n', self.package_name + '/.MainActivity']) + self.run_cmd(['run_simpleperf_without_usb_connection.py', 'start', '-p', + self.package_name]) + self.adb.check_run(['kill-server']) + time.sleep(3) + self.run_cmd(['run_simpleperf_without_usb_connection.py', 'stop']) + self.check_exist(file="perf.data") + self.run_cmd(["report.py", "-g", "-o", "report.txt"]) + class TestExamplePureJavaRoot(TestExampleBase): @classmethod @@ -1050,7 +1060,7 @@ class TestTools(unittest.TestCase): readelf = ReadElf(None) for dso_path in test_map: dso_info = test_map[dso_path] - path = 'testdata' + dso_path + path = 'testdata' + dso_path self.assertEqual(dso_info['arch'], readelf.get_arch(path)) if 'build_id' in dso_info: self.assertEqual(dso_info['build_id'], readelf.get_build_id(path)) |