1# Scripts reference 2 3## Table of Contents 4 5- [Scripts reference](#scripts-reference) 6 - [Table of Contents](#table-of-contents) 7 - [app_profiler.py](#appprofilerpy) 8 - [Profile from launch of an application](#profile-from-launch-of-an-application) 9 - [api_profiler.py](#apiprofilerpy) 10 - [run_simpleperf_without_usb_connection.py](#runsimpleperfwithoutusbconnectionpy) 11 - [binary_cache_builder.py](#binarycachebuilderpy) 12 - [run_simpleperf_on_device.py](#runsimpleperfondevicepy) 13 - [report.py](#reportpy) 14 - [report_html.py](#reporthtmlpy) 15 - [inferno](#inferno) 16 - [purgatorio](#purgatorio) 17 - [pprof_proto_generator.py](#pprofprotogeneratorpy) 18 - [report_sample.py](#reportsamplepy) 19 - [simpleperf_report_lib.py](#simpleperfreportlibpy) 20 21 22## app_profiler.py 23 24app_profiler.py is used to record profiling data for Android applications and native executables. 25 26```sh 27# Record an Android application. 28$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative 29 30# Record an Android application with Java code compiled into native instructions. 31$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative --compile_java_code 32 33# Record the launch of an Activity of an Android application. 34$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative -a .SleepActivity 35 36# Record a native process. 37$ python app_profiler.py -np surfaceflinger 38 39# Record a native process given its pid. 40$ python app_profiler.py --pid 11324 41 42# Record a command. 43$ python app_profiler.py -cmd \ 44 "dex2oat --dex-file=/data/local/tmp/app-profiling.apk --oat-file=/data/local/tmp/a.oat" 45 46# Record an Android application, and use -r to send custom options to the record command. 47$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative \ 48 -r "-e cpu-clock -g --duration 30" 49 50# Record both on CPU time and off CPU time. 51$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative \ 52 -r "-e task-clock -g -f 1000 --duration 10 --trace-offcpu" 53 54# Save profiling data in a custom file (like perf_custom.data) instead of perf.data. 55$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative -o perf_custom.data 56``` 57 58### Profile from launch of an application 59 60Sometimes we want to profile the launch-time of an application. To support this, we added --app in 61the record command. The --app option sets the package name of the Android application to profile. 62If the app is not already running, the record command will poll for the app process in a loop with 63an interval of 1ms. So to profile from launch of an application, we can first start the record 64command with --app, then start the app. Below is an example. 65 66```sh 67$ python run_simpleperf_on_device.py record 68 --app com.example.simpleperf.simpleperfexamplewithnative \ 69 -g --duration 1 -o /data/local/tmp/perf.data 70# Start the app manually or using the `am` command. 71``` 72 73To make it convenient to use, app_profiler.py supports using the -a option to start an Activity 74after recording has started. 75 76```sh 77$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative -a .MainActivity 78``` 79 80## api_profiler.py 81 82api_profiler.py is used to control recording in application code. It does preparation work 83before recording, and collects profiling data files after recording. 84 85[Here](./android_application_profiling.md#control-recording-in-application-code) are the details. 86 87## run_simpleperf_without_usb_connection.py 88 89run_simpleperf_without_usb_connection.py records profiling data while the USB cable isn't 90connected. Maybe api_profiler.py is more suitable, which also don't need USB cable when recording. 91Below is an example. 92 93```sh 94$ python run_simpleperf_without_usb_connection.py start \ 95 -p com.example.simpleperf.simpleperfexamplewithnative 96# After the command finishes successfully, unplug the USB cable, run the 97# SimpleperfExampleWithNative app. After a few seconds, plug in the USB cable. 98$ python run_simpleperf_without_usb_connection.py stop 99# It may take a while to stop recording. After that, the profiling data is collected in perf.data 100# on host. 101``` 102 103## binary_cache_builder.py 104 105The binary_cache directory is a directory holding binaries needed by a profiling data file. The 106binaries are expected to be unstripped, having debug information and symbol tables. The 107binary_cache directory is used by report scripts to read symbols of binaries. It is also used by 108report_html.py to generate annotated source code and disassembly. 109 110By default, app_profiler.py builds the binary_cache directory after recording. But we can also 111build binary_cache for existing profiling data files using binary_cache_builder.py. It is useful 112when you record profiling data using `simpleperf record` directly, to do system wide profiling or 113record without the USB cable connected. 114 115binary_cache_builder.py can either pull binaries from an Android device, or find binaries in 116directories on the host (via -lib). 117 118```sh 119# Generate binary_cache for perf.data, by pulling binaries from the device. 120$ python binary_cache_builder.py 121 122# Generate binary_cache, by pulling binaries from the device and finding binaries in 123# SimpleperfExampleWithNative. 124$ python binary_cache_builder.py -lib path_of_SimpleperfExampleWithNative 125``` 126 127## run_simpleperf_on_device.py 128 129This script pushes the simpleperf executable on the device, and run a simpleperf command on the 130device. It is more convenient than running adb commands manually. 131 132## report.py 133 134report.py is a wrapper of the report command on the host. It accepts all options of the report 135command. 136 137```sh 138# Report call graph 139$ python report.py -g 140 141# Report call graph in a GUI window implemented by Python Tk. 142$ python report.py -g --gui 143``` 144 145## report_html.py 146 147report_html.py generates report.html based on the profiling data. Then the report.html can show 148the profiling result without depending on other files. So it can be shown in local browsers or 149passed to other machines. Depending on which command-line options are used, the content of the 150report.html can include: chart statistics, sample table, flamegraphs, annotated source code for 151each function, annotated disassembly for each function. 152 153```sh 154# Generate chart statistics, sample table and flamegraphs, based on perf.data. 155$ python report_html.py 156 157# Add source code. 158$ python report_html.py --add_source_code --source_dirs path_of_SimpleperfExampleWithNative 159 160# Add disassembly. 161$ python report_html.py --add_disassembly 162 163# Adding disassembly for all binaries can cost a lot of time. So we can choose to only add 164# disassembly for selected binaries. 165$ python report_html.py --add_disassembly --binary_filter libgame.so 166 167# report_html.py accepts more than one recording data file. 168$ python report_html.py -i perf1.data perf2.data 169``` 170 171Below is an example of generating html profiling results for SimpleperfExampleWithNative. 172 173```sh 174$ python app_profiler.py -p com.example.simpleperf.simpleperfexamplewithnative 175$ python report_html.py --add_source_code --source_dirs path_of_SimpleperfExampleWithNative \ 176 --add_disassembly 177``` 178 179After opening the generated [report.html](./report_html.html) in a browser, there are several tabs: 180 181The first tab is "Chart Statistics". You can click the pie chart to show the time consumed by each 182process, thread, library and function. 183 184The second tab is "Sample Table". It shows the time taken by each function. By clicking one row in 185the table, we can jump to a new tab called "Function". 186 187The third tab is "Flamegraph". It shows the graphs generated by [inferno](./inferno.md). 188 189The fourth tab is "Function". It only appears when users click a row in the "Sample Table" tab. 190It shows information of a function, including: 191 1921. A flamegraph showing functions called by that function. 1932. A flamegraph showing functions calling that function. 1943. Annotated source code of that function. It only appears when there are source code files for 195 that function. 1964. Annotated disassembly of that function. It only appears when there are binaries containing that 197 function. 198 199## inferno 200 201[inferno](./inferno.md) is a tool used to generate flamegraph in a html file. 202 203```sh 204# Generate flamegraph based on perf.data. 205# On Windows, use inferno.bat instead of ./inferno.sh. 206$ ./inferno.sh -sc --record_file perf.data 207 208# Record a native program and generate flamegraph. 209$ ./inferno.sh -np surfaceflinger 210``` 211 212## purgatorio 213 214[purgatorio](../scripts/purgatorio/README.md) is a visualization tool to show samples in time order. 215 216## pprof_proto_generator.py 217 218It converts a profiling data file into pprof.proto, a format used by [pprof](https://github.com/google/pprof). 219 220```sh 221# Convert perf.data in the current directory to pprof.proto format. 222$ python pprof_proto_generator.py 223# Show report in pdf format. 224$ pprof -pdf pprof.profile 225 226# Show report in html format. To show disassembly, add --tools option like: 227# --tools=objdump:<ndk_path>/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin 228# To show annotated source or disassembly, select `top` in the view menu, click a function and 229# select `source` or `disassemble` in the view menu. 230$ pprof -http=:8080 pprof.profile 231``` 232 233## report_sample.py 234 235It converts a profiling data file into a format used by [FlameGraph](https://github.com/brendangregg/FlameGraph). 236 237```sh 238# Convert perf.data in the current directory to a format used by FlameGraph. 239$ python report_sample.py --symfs binary_cache >out.perf 240$ git clone https://github.com/brendangregg/FlameGraph.git 241$ FlameGraph/stackcollapse-perf.pl out.perf >out.folded 242$ FlameGraph/flamegraph.pl out.folded >a.svg 243``` 244 245## simpleperf_report_lib.py 246 247simpleperf_report_lib.py is a Python library used to parse profiling data files generated by the 248record command. Internally, it uses libsimpleperf_report.so to do the work. Generally, for each 249profiling data file, we create an instance of ReportLib, pass it the file path (via SetRecordFile). 250Then we can read all samples through GetNextSample(). For each sample, we can read its event info 251(via GetEventOfCurrentSample), symbol info (via GetSymbolOfCurrentSample) and call chain info 252(via GetCallChainOfCurrentSample). We can also get some global information, like record options 253(via GetRecordCmd), the arch of the device (via GetArch) and meta strings (via MetaInfo). 254 255Examples of using simpleperf_report_lib.py are in report_sample.py, report_html.py, 256pprof_proto_generator.py and inferno/inferno.py. 257