Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(474)

Side by Side Diff: tools-webrtc/android/profiling/perf_setup.sh

Issue 2720613008: Adds profiling support for non-rooted devices (Closed)
Patch Set: Initial tests now works for rooted and non-rooted devices Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/bin/bash 1 #!/bin/bash
2 2
3 # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 3 # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
4 # 4 #
5 # Use of this source code is governed by a BSD-style license 5 # Use of this source code is governed by a BSD-style license
6 # that can be found in the LICENSE file in the root of the source 6 # that can be found in the LICENSE file in the root of the source
7 # tree. An additional intellectual property rights grant can be found 7 # tree. An additional intellectual property rights grant can be found
8 # in the file PATENTS. All contributing project authors may 8 # in the file PATENTS. All contributing project authors may
9 # be found in the AUTHORS file in the root of the source tree. 9 # be found in the AUTHORS file in the root of the source tree.
10 # 10 #
11 # Usage: 11 # Usage:
12 # 12 #
13 # It is assumed that a release build of AppRTCMobile exists and has been 13 # It is assumed that a release build of AppRTCMobile exists and has been
14 # installed on a rooted and attached Android device. 14 # installed on an Android device which supports USB debugging.
15 # 15 #
16 # Source this script once from the WebRTC src/ directory and resolve any 16 # Source this script once from the WebRTC src/ directory and resolve any
17 # reported issues. Add relative path to build directory as parameter. 17 # reported issues. Add relative path to build directory as parameter.
18 # Required tools will be downloaded if they don't already exist. 18 # Required tools will be downloaded if they don't already exist.
19 # 19 #
20 # Once all tests are passed, a list of available functions will be given. 20 # Once all tests are passed, a list of available functions will be given.
21 # Use these functions to do the actual profiling and visualization of the 21 # Use these functions to do the actual profiling and visualization of the
22 # results. 22 # results.
23 # 23 #
24 # Note that, using a rooted device is recommended since it allows us to
25 # resolve kernel symbols (kallsyms) as well.
26 #
24 # Example usage: 27 # Example usage:
25 # 28 #
26 # > . tools-webrtc/android/profiling/perf_setup.sh out/Release 29 # > . tools-webrtc/android/profiling/perf_setup.sh out/Release
27 # > perf_record 120 30 # > perf_record 120
28 # > flame_graph 31 # > flame_graph
29 # > plot_flame_graph 32 # > plot_flame_graph
30 # > perf_cleanup 33 # > perf_cleanup
31 34
32 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" 35 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
33 source "${SCRIPT_DIR}/utilities.sh" 36 source "${SCRIPT_DIR}/utilities.sh"
(...skipping 19 matching lines...) Expand all
53 56
54 # Ensure that user includes name of build directory (e.g. out/Release) as 57 # Ensure that user includes name of build directory (e.g. out/Release) as
55 # input parameter. Store path in BUILD_DIR. 58 # input parameter. Store path in BUILD_DIR.
56 if [[ "$#" -eq 1 ]]; then 59 if [[ "$#" -eq 1 ]]; then
57 if is_not_dir "$1"; then 60 if is_not_dir "$1"; then
58 error "$1 is invalid" 61 error "$1 is invalid"
59 return 1 62 return 1
60 fi 63 fi
61 BUILD_DIR="$1" 64 BUILD_DIR="$1"
62 else 65 else
63 unset BUILD_DIR
64 error "Missing required parameter". 66 error "Missing required parameter".
65 usage 67 usage
68 return 1
66 fi 69 fi
67 70
68 # Helper method to simpify usage of the simpleperf binary on the device.
69 function simpleperf_android() {
70 local simpleperf="${DEV_TMP_DIR}/simpleperf"
71 if [ ! -z "$1" ]; then
72 adb shell "${simpleperf}" "$@"
73 else
74 adb shell $simpleperf --help
75 fi
76 }
77
78 # Full (relative) path to the libjingle_peerconnection_so.so file. 71 # Full (relative) path to the libjingle_peerconnection_so.so file.
79 function native_shared_lib_path() { 72 function native_shared_lib_path() {
80 echo "${BUILD_DIR}${NATIVE_LIB_PATH}" 73 echo "${BUILD_DIR}${NATIVE_LIB_PATH}"
81 } 74 }
82 75
83 # Target CPU architecture for the native shared library. 76 # Target CPU architecture for the native shared library.
84 # Example: AArch64. 77 # Example: AArch64.
85 function native_shared_lib_arch() { 78 function native_shared_lib_arch() {
86 readelf -h $(native_shared_lib_path) | grep Machine | awk '{print $2}' 79 readelf -h $(native_shared_lib_path) | grep Machine | awk '{print $2}'
87 } 80 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 adb pull /proc/kallsyms "${symbol_cache}" 112 adb pull /proc/kallsyms "${symbol_cache}"
120 } 1> /dev/null 113 } 1> /dev/null
121 114
122 # Download the correct version of 'simpleperf' to $DEV_TMP_DIR 115 # Download the correct version of 'simpleperf' to $DEV_TMP_DIR
123 # on the device and enable profiling. 116 # on the device and enable profiling.
124 function copy_simpleperf_to_device() { 117 function copy_simpleperf_to_device() {
125 local perf_binary 118 local perf_binary
126 [[ $(dev_arch) == "aarch64" ]] \ 119 [[ $(dev_arch) == "aarch64" ]] \
127 && perf_binary="/arm64/simpleperf" \ 120 && perf_binary="/arm64/simpleperf" \
128 || perf_binary="/arm/simpleperf" 121 || perf_binary="/arm/simpleperf"
129 local simpleperf="${DEV_TMP_DIR}/simpleperf"
130 # Copy the simpleperf binary from local host to temp folder on device. 122 # Copy the simpleperf binary from local host to temp folder on device.
131 adb push "${SCRIPT_DIR}/simpleperf/bin/android${perf_binary}" \ 123 adb push "${SCRIPT_DIR}/simpleperf/bin/android${perf_binary}" \
132 "${DEV_TMP_DIR}" 1> /dev/null 124 "${DEV_TMP_DIR}" 1> /dev/null
133 adb shell chmod a+x $simpleperf 125 # Copy simpleperf from temp folder to the application package.
126 adb shell run-as "${APP_NAME}" cp "${DEV_TMP_DIR}/simpleperf" .
127 adb shell run-as "${APP_NAME}" chmod a+x simpleperf
134 # Enable profiling on the device. 128 # Enable profiling on the device.
135 enable_profiling 129 enable_profiling
136 # Allows usage of running report commands on the device. 130 # Allows usage of running report commands on the device.
137 if image_is_root; then 131 if image_is_root; then
138 enable_report_symbols 132 enable_report_symbols
139 fi 133 fi
140 } 134 }
141 135
142 # Copy the recorded 'perf.data' file from the device to the current directory. 136 # Copy the recorded 'perf.data' file from the device to the current directory.
143 # TODO(henrika): add support for specifying the destination. 137 # TODO(henrika): add support for specifying the destination.
144 function pull_perf_data_from_device() { 138 function pull_perf_data_from_device() {
145 adb pull "${DEV_TMP_DIR}/perf.data" . 139 adb shell run-as "${APP_NAME}" cp perf.data /sdcard/perf.data
140 adb pull sdcard/perf.data .
146 } 1> /dev/null 141 } 1> /dev/null
147 142
148 143
149 # Wraps calls to simpleperf report. Used by e.g. perf_report_threads. 144 # Wraps calls to simpleperf report. Used by e.g. perf_report_threads.
150 # A valid profile input file must exist in the current folder. 145 # A valid profile input file must exist in the current folder.
151 # TODO(henrika): possibly add support to add path to alternative input file. 146 # TODO(henrika): possibly add support to add path to alternative input file.
152 function perf_report() { 147 function perf_report() {
153 local perf_data="perf.data" 148 local perf_data="perf.data"
154 is_file "${perf_data}" \ 149 is_file "${perf_data}" \
155 && simpleperf report \ 150 && simpleperf report \
(...skipping 29 matching lines...) Expand all
185 # Lists the main available functions after sourcing this script. 180 # Lists the main available functions after sourcing this script.
186 function print_function_help() { 181 function print_function_help() {
187 printf "\nAvailable functions in this shell:\n" 182 printf "\nAvailable functions in this shell:\n"
188 printf " perf_record [duration, default=60sec]\n" 183 printf " perf_record [duration, default=60sec]\n"
189 printf " perf_report_threads\n" 184 printf " perf_report_threads\n"
190 printf " perf_report_bins\n" 185 printf " perf_report_bins\n"
191 printf " perf_report_symbols\n" 186 printf " perf_report_symbols\n"
192 printf " perf_report_graph\n" 187 printf " perf_report_graph\n"
193 printf " perf_report_graph_callee\n" 188 printf " perf_report_graph_callee\n"
194 printf " perf_update\n" 189 printf " perf_update\n"
195 printf " perf_clean\n" 190 printf " perf_cleanup\n"
196 printf " flame_graph\n" 191 printf " flame_graph\n"
197 printf " plot_flame_graph\n" 192 printf " plot_flame_graph\n"
198 } 193 }
199 194
200 function cleanup() { 195 function cleanup() {
201 unset -f main 196 unset -f main
202 } 197 }
203 198
204 # ----------------------------------------------------------------------------- 199 # -----------------------------------------------------------------------------
205 # Main methods to be used after sourcing the main script. 200 # Main methods to be used after sourcing the main script.
206 # ----------------------------------------------------------------------------- 201 # -----------------------------------------------------------------------------
207 202
208 # Call this method after the application as been rebuilt and installed on the 203 # Call this method after the application as been rebuilt and installed on the
209 # device to ensure that symbols are up-to-date. 204 # device to ensure that symbols are up-to-date.
210 function perf_update() { 205 function perf_update() {
211 copy_native_shared_library_to_symbol_cache 206 copy_native_shared_library_to_symbol_cache
212 copy_kernel_symbols_from_device_to_symbol_cache 207 if image_is_root; then
208 copy_kernel_symbols_from_device_to_symbol_cache
209 fi
213 } 210 }
214 211
215 # Record stack frame based call graphs while using the application. 212 # Record stack frame based call graphs while using the application.
216 # We use default events (cpu-cycles), and write records to 'perf.data' in the 213 # We use default events (cpu-cycles), and write records to 'perf.data' in the
217 # tmp folder on the device. Default duration is 60 seconds but it can be changed 214 # tmp folder on the device. Default duration is 60 seconds but it can be changed
218 # by adding one parameter. As soon as the recording is done, 'perf.data' is 215 # by adding one parameter. As soon as the recording is done, 'perf.data' is
219 # copied to the directory from which this method is called and a summary of 216 # copied to the directory from which this method is called and a summary of
220 # the load distribution per thread is printed. 217 # the load distribution per thread is printed.
221 function perf_record() { 218 function perf_record() {
222 if app_is_running "${APP_NAME}"; then 219 if app_is_running "${APP_NAME}"; then
223 # Ensure that the latest native shared library exists in the local cache. 220 # Ensure that the latest native shared library exists in the local cache.
224 copy_native_shared_library_to_symbol_cache 221 copy_native_shared_library_to_symbol_cache
225 local duration=60 222 local duration=60
226 if [ "$#" -eq 1 ]; then 223 if [ "$#" -eq 1 ]; then
227 duration="$1" 224 duration="$1"
228 fi 225 fi
229 local pid=$(find_app_pid "${APP_NAME}") 226 local pid=$(find_app_pid "${APP_NAME}")
230 echo "Profiling PID $pid for $duration seconds (media must be is active)..." 227 echo "Profiling PID $pid for $duration seconds (media must be is active)..."
231 local output_file="${DEV_TMP_DIR}/perf.data" 228 adb shell run-as "${APP_NAME}" ./simpleperf record \
232 simpleperf_android record \
233 --call-graph fp \ 229 --call-graph fp \
234 -p "${pid}" \ 230 -p "${pid}" \
235 -o $output_file \
236 -f 1000 \ 231 -f 1000 \
237 --duration "${duration}" \ 232 --duration "${duration}" \
238 --log error 233 --log error
239 app_stop "${APP_NAME}"
240 # Copy profile results from device to current directory. 234 # Copy profile results from device to current directory.
241 pull_perf_data_from_device 235 pull_perf_data_from_device
242 # Print out a summary report (load per thread). 236 # Print out a summary report (load per thread).
243 perf_report_threads | tail -n +6 237 perf_report_threads | tail -n +6
244 else 238 else
245 # AppRTCMobile was not enabled. Start it up automatically and ask the user 239 # AppRTCMobile was not enabled. Start it up automatically and ask the user
246 # to start media and then call this method again. 240 # to start media and then call this method again.
247 warning "AppRTCMobile must be active" 241 warning "AppRTCMobile must be active"
248 app_start "${APP_NAME}" 242 app_start "${APP_NAME}"
249 echo "Start media and then call perf_record again..." 243 echo "Start media and then call perf_record again..."
250 fi 2> /dev/null 244 fi
251 } 245 }
252 246
253 # Analyze the profile report and show samples per threads. 247 # Analyze the profile report and show samples per threads.
254 function perf_report_threads() { 248 function perf_report_threads() {
255 perf_report --sort comm 249 perf_report --sort comm
256 } 2> /dev/null 250 } 2> /dev/null
257 251
258 # Analyze the profile report and show samples per binary. 252 # Analyze the profile report and show samples per binary.
259 function perf_report_bins() { 253 function perf_report_bins() {
260 perf_report --sort dso 254 perf_report --sort dso
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 fi 296 fi
303 local file_name="flame_graph.svg" 297 local file_name="flame_graph.svg"
304 local title="WebRTC Flame Graph" 298 local title="WebRTC Flame Graph"
305 if [[ "$#" -eq 1 ]]; then 299 if [[ "$#" -eq 1 ]]; then
306 file_name="$1" 300 file_name="$1"
307 fi 301 fi
308 if [[ "$#" -eq 2 ]]; then 302 if [[ "$#" -eq 2 ]]; then
309 file_name="$1" 303 file_name="$1"
310 title="$2" 304 title="$2"
311 fi 305 fi
312 report_sample.py \ 306 if image_is_not_root; then
313 --symfs "${SYMBOL_DIR}" \ 307 report_sample.py \
314 --kallsyms "${SYMBOL_DIR}/kallsyms" \ 308 --symfs "${SYMBOL_DIR}" \
315 perf.data >out.perf 309 perf.data >out.perf
310 else
311 report_sample.py \
312 --symfs "${SYMBOL_DIR}" \
313 --kallsyms "${SYMBOL_DIR}/kallsyms" \
314 perf.data >out.perf
315 fi
316 stackcollapse-perf.pl out.perf >out.folded 316 stackcollapse-perf.pl out.perf >out.folded
317 flamegraph.pl --title="${title}" out.folded >"${file_name}" 317 flamegraph.pl --title="${title}" out.folded >"${file_name}"
318 rm out.perf 318 rm out.perf
319 rm out.folded 319 rm out.folded
320 } 320 }
321 321
322 # Remove all downloaded third-party tools. 322 # Remove all downloaded third-party tools.
323 function perf_cleanup () { 323 function perf_cleanup () {
324 rm_simpleperf 324 rm_simpleperf
325 rm_flame_graph 325 rm_flame_graph
(...skipping 28 matching lines...) Expand all
354 fi 354 fi
355 ok "adb tool is working" 355 ok "adb tool is working"
356 356
357 # Exactly one Android device must be connected. 357 # Exactly one Android device must be connected.
358 if [[ ! one_device_connected ]]; then 358 if [[ ! one_device_connected ]]; then
359 error "one device must be connected" 359 error "one device must be connected"
360 return 1 360 return 1
361 fi 361 fi
362 ok "one device is connected via USB" 362 ok "one device is connected via USB"
363 363
364 # Ensure that the device is rooted. 364 # Restart adb with root permissions if needed.
365 if image_is_not_root; then 365 if image_is_root && adb_has_no_root_permissions; then
366 error "device is not rooted" 366 adb root
367 return 1 367 ok "adb is running as root"
368 fi 368 fi
369 ok "device is rooted"
370
371 # Restart adb with root permissions if needed.
372 if adb_has_no_root_permissions; then
373 adb root
374 fi
375 ok "adbd is running as root"
376 369
377 # Create an empty symbol cache in the tmp folder. 370 # Create an empty symbol cache in the tmp folder.
378 # TODO(henrika): it might not be required to start from a clean cache. 371 # TODO(henrika): it might not be required to start from a clean cache.
379 is_dir "${SYMBOL_DIR}" && rm -rf "${SYMBOL_DIR}" 372 is_dir "${SYMBOL_DIR}" && rm -rf "${SYMBOL_DIR}"
380 mkdir "${SYMBOL_DIR}" \ 373 mkdir "${SYMBOL_DIR}" \
381 && ok "empty symbol cache created at ${SYMBOL_DIR}" \ 374 && ok "empty symbol cache created at ${SYMBOL_DIR}" \
382 || error "failed to create symbol cache" 375 || error "failed to create symbol cache"
383 376
384 # Ensure that path to the native library with symbols is valid. 377 # Ensure that path to the native library with symbols is valid.
385 local native_lib=$(native_shared_lib_path) 378 local native_lib=$(native_shared_lib_path)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 454
462 cleanup 455 cleanup
463 456
464 return 0 457 return 0
465 } 458 }
466 459
467 # Only call main() if proper input parameter has been provided. 460 # Only call main() if proper input parameter has been provided.
468 if is_set $BUILD_DIR; then 461 if is_set $BUILD_DIR; then
469 main "$@" 462 main "$@"
470 fi 463 fi
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698