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