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

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

Issue 2705063002: Adding support for native profiling of AppRTCMobile (Closed)
Patch Set: nit Created 3 years, 10 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
OLDNEW
(Empty)
1 #!/bin/bash
2
3 # Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
4 #
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
7 # tree. An additional intellectual property rights grant can be found
8 # in the file PATENTS. All contributing project authors may
9 # be found in the AUTHORS file in the root of the source tree.
10 #
11 # Usage:
12 #
13 # It is assumed that a release build of AppRTCMobile exists and has been
14 # installed on a rooted and attached Android device.
15 #
16 # Source this script once from the WebRTC source directory and resolve any
17 # reported issues. Add relative path to build directory as parameter.
18 #
19 # Once all tests are passed, a list of available functions will be listed.
20 # Use these functions to do the actual profiling and visualization of the
21 # results.
22 #
23 # Example:
24 #
25 # >> . tools-webrtc/android/profiling/perf_setup.sh out/Release
26 # >> perf_record 60
27 # >> perf_report_symbols
28 #
29 # TODO(henrika): add more here for Flame Graph plots...
30
31 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
32 source "${SCRIPT_DIR}/utilities.sh"
33
34 # Root directory for local symbol cache.
35 SYMBOL_DIR="${TMPDIR:-/tmp}/android_symbols"
36 # Root directory to prebuilt (Android and Linux) versions of simpleperf.
37 SIMPLE_PERF_ROOT_DIR="${SCRIPT_DIR}/simpleperf/bin"
38 # Used as a temporary folder on the Android device for data storage.
39 DEV_TMP_DIR="/data/local/tmp"
40 # Relative path to native shared library containing symbols.
41 NATIVE_LIB_PATH="/lib.unstripped/libjingle_peerconnection_so.so"
42 # Name of application package for the AppRTCMobile demo.
43 APP_NAME="org.appspot.apprtc"
44
45 # Make sure we're being sourced.
46 if [[ -n "${BASH_VERSION}" && "${BASH_SOURCE:-$0}" == "$0" ]]; then
47 error "perf_setup must be sourced!"
48 exit 1
49 fi
50
51 function usage() {
52 printf "usage: . perf_setup.sh <build_dir>\n"
53 printf "Example: . perf_setup.sh out/Release\n"
54 }
55
56 # Ensure that user includes name of build directory (e.g. out/Release) as
57 # input parameter. Store path in BUILD_DIR.
58 if [[ "$#" -eq 1 ]]; then
59 BUILD_DIR="$1"
60 else
61 unset BUILD_DIR
kjellander_webrtc 2017/02/22 14:46:57 Why unset it?
henrika_webrtc 2017/02/22 15:47:11 Long story. But essentially. If I don't do it, we
kjellander_webrtc 2017/02/24 11:02:25 Acknowledged.
62 error "Missing required parameter".
63 usage
64 fi
65
66 # Helper method to simpify usage of the simpleperf binary on the device.
67 function simpleperf_android() {
68 local simpleperf="${DEV_TMP_DIR}/simpleperf"
69 if [ ! -z "$1" ]; then
70 adb shell "${simpleperf}" "$@"
71 else
72 adb shell $simpleperf --help
73 fi
74 }
75
76 # Full (relative) path to the libjingle_peerconnection_so.so file.
77 function native_shared_lib_path() {
78 echo "${BUILD_DIR}${NATIVE_LIB_PATH}"
79 }
80
81 # Target CPU architecture for the native shared library.
82 # Example: AArch64.
83 function native_shared_lib_arch() {
84 readelf -h $(native_shared_lib_path) | grep Machine | awk '{print $2}'
85 }
86
87 # Returns true if the device architecture and the build target are the same.
88 function arch_is_ok() {
89 if [[ "$(dev_arch)" == "aarch64" ]] \
90 && [[ "$(native_shared_lib_arch)" == "AArch64" ]]; then
91 return 0
92 elif [[ "$(dev_arch)" == "aarch32" ]] \
93 && [[ "$(native_shared_lib_arch)" == "AArch32" ]]; then
94 return 0
95 else
96 return 1
97 fi
98 }
99
100 # Copies the native shared library from the local host to the symbol cache
101 # which is used by simpleperf as base when searching for symbols.
102 function copy_native_shared_library_to_symbol_cache() {
103 local arm_lib="arm"
104 if [ "$(native_shared_lib_arch)" == "AArch64" ]; then
105 arm_lib="arm64"
106 fi
107 for num in 1 2; do
108 local dir="${SYMBOL_DIR}/data/app/${APP_NAME}-${num}/lib/${arm_lib}"
109 mkdir -p "${dir}"
110 cp -u $(native_shared_lib_path) "${dir}"
111 done
112 }
113
114 # Copy kernal symbols from device to symbol cache in tmp.
115 function copy_kernal_symbols_from_device_to_symbol_cache() {
116 local symbol_cache="${SYMBOL_DIR}/kallsyms"
117 adb pull /proc/kallsyms "${symbol_cache}"
118 } 1> /dev/null
119
120 # Download the correct version of 'simpleperf' to $DEV_TMP_DIR
121 # on the device and enable profiling.
122 function copy_simpleperf_to_device() {
123 local perf_binary
124 [[ $(dev_arch) == "aarch64" ]] \
125 && perf_binary="/arm64/simpleperf" \
126 || perf_binary="/arm/simpleperf"
127 local simpleperf="${DEV_TMP_DIR}/simpleperf"
128 # Avoid copying to device if simpleperf already exists.
129 if [[ ! $(dev_ls "${simpleperf}") ]]; then
130 adb push "${SIMPLE_PERF_DIR}${perf_binary}" "${DEV_TMP_DIR}"
131 adb shell chmod a+x $simpleperf
132 fi
133 # Enable profiling on the device.
134 enable_profiling
135 # Allows usgage of running report commands on the device.
kjellander_webrtc 2017/02/22 14:46:57 usgage -> usage?
henrika_webrtc 2017/02/22 15:47:11 Done.
136 enable_report_symbols
137 }
138
139 # Copy the recorded 'perf.data' file from the device to the current directory.
140 # TODO(henrika): add support for specifying the destination.
141 function pull_perf_data_from_device() {
142 adb pull "${DEV_TMP_DIR}/perf.data" .
143 } 1> /dev/null
144
145
146 # Wraps calls to simpleperf report. Used by e.g. perf_report_threads.
147 # A valid profile input file must exist in the current folder.
148 # TODO(henrika): possibly add support to add path to alternative input file.
149 function perf_report() {
150 local perf_data="perf.data"
151 is_file "${perf_data}" \
152 && simpleperf report \
153 -n \
154 -i "${perf_data}" \
155 "$@" \
156 || error "$(pwd)/${perf_data} is invalid!"
157 }
158
159 # Lists the main available functions after sourcing this script.
160 function print_function_help() {
161 printf "\nAvailable functions:\n"
162 printf " perf_record [duration, default=30sec]\n"
163 printf " perf_report_threads\n"
164 printf " perf_report_bins\n"
165 printf " perf_report_symbols\n"
166 printf " perf_update\n"
167 }
168
169 function cleanup() {
170 unset -f main
171 }
172
173 # -----------------------------------------------------------------------------
174 # Main methods to be used after sourcing the main script.
175 # -----------------------------------------------------------------------------
176
177 # Call this method after the application as been rebuilt and installed on the
178 # device to ensure that symbols are up-to-date.
179 function perf_update() {
180 copy_native_shared_library_to_symbol_cache
181 copy_kernal_symbols_from_device_to_symbol_cache
182 }
183
184 # Record stack frame based call graphs while using the application.
185 # We use default events (cpu-cycles), and write records to 'perf.data' in the
186 # tmp folder on the device. Default duration is 30 seconds but it can be changed
187 # by adding one parameter. As soon as the recording is done, 'perf.data' is
188 # copied to the directoty from which this method is called.
189 function perf_record() {
190 if app_is_running "${APP_NAME}"; then
191 # Ensure that the latest native shared library exists in the local cache.
192 copy_native_shared_library_to_symbol_cache
193 local duration=30
194 if [ "$#" -eq 1 ]; then
195 duration="$1"
196 fi
197 local pid=$(find_app_pid "${APP_NAME}")
198 echo "Profiling PID $pid for $duration seconds (media must be is active)..."
199 local output_file="${DEV_TMP_DIR}/perf.data"
200 simpleperf_android record \
201 --call-graph fp \
202 -p "${pid}" \
203 -o $output_file \
204 -f 1000 \
205 --duration "${duration}" \
206 --log error
207 app_stop "${APP_NAME}"
208 # Copy profile results from device to current directory.
209 pull_perf_data_from_device
210 # Print out a summary report (load per thread).
211 perf_report_threads | tail -n +6
212 else
213 # AppRTCMobile was not enabled. Start it up automatically and ask the user
214 # to start media and then call this method again.
215 warning "AppRTCMobile must be active"
216 app_start "${APP_NAME}"
217 echo "Start media and then call perf_record() again..."
218 fi 2> /dev/null
219 }
220
221 # Analyze the profile report and show samples per threads.
222 function perf_report_threads() {
223 perf_report --sort comm
224 } 2> /dev/null
225
226 # Analyze the profile report and show samples per binary.
227 function perf_report_bins() {
228 perf_report --sort dso
229 } 2> /dev/null
230
231 # Analyze the profile report and show samples per symbol.
232 function perf_report_symbols() {
233 perf_report --sort symbol --symfs "${SYMBOL_DIR}"
234 }
235
236 # -----------------------------------------------------------------------------
237 # TODO(henrika): add comments...
kjellander_webrtc 2017/02/22 14:46:57 Which ones are you referring to? I think it's pret
henrika_webrtc 2017/02/22 15:47:10 Removed.
238 # -----------------------------------------------------------------------------
239
240 main() {
241 printf "%s\n" "Preparing profiling of AppRTCMobile on Android:"
242 # Verify that this script is called from the root folder of WebRTC,
243 # i.e., the src folder one step below where the .gclient file exists.
244 local -r project_root_dir=$(pwd)
245 local dir=${project_root_dir##*/}
246 if [[ "${dir}" != "src" ]]; then
247 error "script must be called from the WebRTC project root (src) folder"
248 return 1
249 fi
250 ok "project root: ${project_root_dir}"
251
252 # Verify that user has sourced envsetup.sh.
253 # TODO(henrika): might be possible to remove this check.
254 if [[ -z "$ENVSETUP_GYP_CHROME_SRC" ]]; then
kjellander_webrtc 2017/02/22 14:46:57 This sounds like something that might go away. May
henrika_webrtc 2017/02/22 15:47:11 I have not found any other way actually. It works
255 error "must source envsetup script first"
256 return 1
257 fi
258 ok "envsetup script has been sourced"
259
260 # Given that envsetup is sourced, the adb tool should be accessible but
261 # do one extra check just in case.
262 local adb_full_path=$(which adb);
263 if [[ ! -x "${adb_full_path}" ]]; then
264 error "unable to find the Android Debug Bridge (adb) tool"
265 return 1
266 fi
267 ok "adb tool is working"
268
269 # Exactly one Android device must be connected.
270 if [[ ! one_device_connected ]]; then
271 error "one device must be connected!"
272 return 1
273 fi
274 ok "one device is connected via USB"
275
276 # Ensure that the device is rooted.
277 if image_is_not_root; then
278 error "device is not rooted!"
279 return 1
280 fi
281 ok "device is rooted"
282
283 # Restart adb with root permissions if needed.
284 if adb_has_no_root_permissions; then
285 adb root
286 fi
287 ok "adbd is running as root"
288
289 # Create an empty symbol cache in the tmp folder.
290 # TODO(henrika): it might not be required to start from a clean cache.
291 is_dir "${SYMBOL_DIR}" && rm -rf "${SYMBOL_DIR}"
292 mkdir "${SYMBOL_DIR}" \
293 && ok "empty symbol cache created at ${SYMBOL_DIR}" \
294 || error "failed to create symbol cache"
295
296 # Ensure that path to the native library with symbols is valid.
297 local native_lib=$(native_shared_lib_path)
298 if is_not_file ${native_lib}; then
299 error "${native_lib} is not a valid file"
300 return 1
301 fi
302 ok "native library: "${native_lib}""
303
304 # Verify that the architechture of the device matches the architecture
305 # of the native library.
306 if ! arch_is_ok; then
307 error "device is $(dev_arch) and lib is $(native_shared_lib_arch)"
308 return 1
309 fi
310 ok "device is $(dev_arch) and lib is $(native_shared_lib_arch)"
311
312 # Copy native shared library to symbol cache after creating an
313 # application specific tree structure under ${SYMBOL_DIR}/data.
314 copy_native_shared_library_to_symbol_cache
315 ok "native library copied to ${SYMBOL_DIR}/data/app/${APP_NAME}"
316
317 # Verify that the application is installed on the device.
318 if ! app_is_installed "${APP_NAME}"; then
319 error "${APP_NAME} is not installed on the device"
320 return 1
321 fi
322 ok "${APP_NAME} is installed on the device"
323
324 # Ensure that folder for simpleperf executables (Android and Linux) exist
325 # as it should relative to the working directory (source of WebRTC).
326 if is_not_dir "${SIMPLE_PERF_ROOT_DIR}"; then
327 error "${SIMPLE_PERF_ROOT_DIR} is invalid"
328 return 1
329 fi
330 ok "${SIMPLE_PERF_ROOT_DIR} is valid"
331
332 # Update the PATH variable with the path to the Linux version of simpleperf.
333 local simpleperf_linux_dir="${SCRIPT_DIR}/simpleperf/bin/linux/x86_64/"
334 if is_not_dir "${simpleperf_linux_dir}"; then
335 error "${simpleperf_linux_dir} is invalid"
336 return 1
337 fi
338 path_update "${simpleperf_linux_dir}"
339 ok "${simpleperf_linux_dir}" is added to PATH
340
341 # Copy correct version (arm or arm64) of simpleperf to the device
342 # and enable profiling at the same time.
343 if ! copy_simpleperf_to_device; then
344 error "failed to install simpleperf on the device"
345 return 1
346 fi
347 ok "simpleperf is installed on the device"
348
349 # Refresh the symbol cache as last step. Now also reading kernal symbols
350 # from device if not already done.
351 perf_update
352 ok "symbol cache is updated"
353
354 print_function_help
355
356 cleanup
357
358 return 0
359 }
360
361 # Only call main() if proper input parameter has been provided.
362 if is_set $BUILD_DIR; then
363 main "$@"
364 fi
OLDNEW
« no previous file with comments | « no previous file | tools-webrtc/android/profiling/utilities.sh » ('j') | tools-webrtc/android/profiling/utilities.sh » ('J')

Powered by Google App Engine
This is Rietveld 408576698