Adds profiling support for non-rooted devices.

NOTRY=TRUE
TBR=kjellander
BUG=NONE

Review-Url: https://codereview.webrtc.org/2720613008
Cr-Commit-Position: refs/heads/master@{#16901}
This commit is contained in:
henrika
2017-02-28 05:55:44 -08:00
committed by Commit bot
parent 3fd31fe502
commit c6106f4102

View File

@ -11,7 +11,7 @@
# Usage: # Usage:
# #
# It is assumed that a release build of AppRTCMobile exists and has been # It is assumed that a release build of AppRTCMobile exists and has been
# installed on a rooted and attached Android device. # installed on an Android device which supports USB debugging.
# #
# Source this script once from the WebRTC src/ directory and resolve any # Source this script once from the WebRTC src/ directory and resolve any
# reported issues. Add relative path to build directory as parameter. # reported issues. Add relative path to build directory as parameter.
@ -21,6 +21,9 @@
# Use these functions to do the actual profiling and visualization of the # Use these functions to do the actual profiling and visualization of the
# results. # results.
# #
# Note that, using a rooted device is recommended since it allows us to
# resolve kernel symbols (kallsyms) as well.
#
# Example usage: # Example usage:
# #
# > . tools-webrtc/android/profiling/perf_setup.sh out/Release # > . tools-webrtc/android/profiling/perf_setup.sh out/Release
@ -60,21 +63,11 @@ if [[ "$#" -eq 1 ]]; then
fi fi
BUILD_DIR="$1" BUILD_DIR="$1"
else else
unset BUILD_DIR
error "Missing required parameter". error "Missing required parameter".
usage usage
return 1
fi fi
# Helper method to simpify usage of the simpleperf binary on the device.
function simpleperf_android() {
local simpleperf="${DEV_TMP_DIR}/simpleperf"
if [ ! -z "$1" ]; then
adb shell "${simpleperf}" "$@"
else
adb shell $simpleperf --help
fi
}
# Full (relative) path to the libjingle_peerconnection_so.so file. # Full (relative) path to the libjingle_peerconnection_so.so file.
function native_shared_lib_path() { function native_shared_lib_path() {
echo "${BUILD_DIR}${NATIVE_LIB_PATH}" echo "${BUILD_DIR}${NATIVE_LIB_PATH}"
@ -126,11 +119,12 @@ function copy_simpleperf_to_device() {
[[ $(dev_arch) == "aarch64" ]] \ [[ $(dev_arch) == "aarch64" ]] \
&& perf_binary="/arm64/simpleperf" \ && perf_binary="/arm64/simpleperf" \
|| perf_binary="/arm/simpleperf" || perf_binary="/arm/simpleperf"
local simpleperf="${DEV_TMP_DIR}/simpleperf"
# Copy the simpleperf binary from local host to temp folder on device. # Copy the simpleperf binary from local host to temp folder on device.
adb push "${SCRIPT_DIR}/simpleperf/bin/android${perf_binary}" \ adb push "${SCRIPT_DIR}/simpleperf/bin/android${perf_binary}" \
"${DEV_TMP_DIR}" 1> /dev/null "${DEV_TMP_DIR}" 1> /dev/null
adb shell chmod a+x $simpleperf # Copy simpleperf from temp folder to the application package.
adb shell run-as "${APP_NAME}" cp "${DEV_TMP_DIR}/simpleperf" .
adb shell run-as "${APP_NAME}" chmod a+x simpleperf
# Enable profiling on the device. # Enable profiling on the device.
enable_profiling enable_profiling
# Allows usage of running report commands on the device. # Allows usage of running report commands on the device.
@ -142,7 +136,8 @@ function copy_simpleperf_to_device() {
# Copy the recorded 'perf.data' file from the device to the current directory. # Copy the recorded 'perf.data' file from the device to the current directory.
# TODO(henrika): add support for specifying the destination. # TODO(henrika): add support for specifying the destination.
function pull_perf_data_from_device() { function pull_perf_data_from_device() {
adb pull "${DEV_TMP_DIR}/perf.data" . adb shell run-as "${APP_NAME}" cp perf.data /sdcard/perf.data
adb pull sdcard/perf.data .
} 1> /dev/null } 1> /dev/null
@ -192,7 +187,7 @@ function print_function_help() {
printf " perf_report_graph\n" printf " perf_report_graph\n"
printf " perf_report_graph_callee\n" printf " perf_report_graph_callee\n"
printf " perf_update\n" printf " perf_update\n"
printf " perf_clean\n" printf " perf_cleanup\n"
printf " flame_graph\n" printf " flame_graph\n"
printf " plot_flame_graph\n" printf " plot_flame_graph\n"
} }
@ -209,7 +204,9 @@ function cleanup() {
# device to ensure that symbols are up-to-date. # device to ensure that symbols are up-to-date.
function perf_update() { function perf_update() {
copy_native_shared_library_to_symbol_cache copy_native_shared_library_to_symbol_cache
copy_kernel_symbols_from_device_to_symbol_cache if image_is_root; then
copy_kernel_symbols_from_device_to_symbol_cache
fi
} }
# Record stack frame based call graphs while using the application. # Record stack frame based call graphs while using the application.
@ -228,15 +225,12 @@ function perf_record() {
fi fi
local pid=$(find_app_pid "${APP_NAME}") local pid=$(find_app_pid "${APP_NAME}")
echo "Profiling PID $pid for $duration seconds (media must be is active)..." echo "Profiling PID $pid for $duration seconds (media must be is active)..."
local output_file="${DEV_TMP_DIR}/perf.data" adb shell run-as "${APP_NAME}" ./simpleperf record \
simpleperf_android record \
--call-graph fp \ --call-graph fp \
-p "${pid}" \ -p "${pid}" \
-o $output_file \
-f 1000 \ -f 1000 \
--duration "${duration}" \ --duration "${duration}" \
--log error --log error
app_stop "${APP_NAME}"
# Copy profile results from device to current directory. # Copy profile results from device to current directory.
pull_perf_data_from_device pull_perf_data_from_device
# Print out a summary report (load per thread). # Print out a summary report (load per thread).
@ -247,7 +241,7 @@ function perf_record() {
warning "AppRTCMobile must be active" warning "AppRTCMobile must be active"
app_start "${APP_NAME}" app_start "${APP_NAME}"
echo "Start media and then call perf_record again..." echo "Start media and then call perf_record again..."
fi 2> /dev/null fi
} }
# Analyze the profile report and show samples per threads. # Analyze the profile report and show samples per threads.
@ -309,10 +303,16 @@ function flame_graph() {
file_name="$1" file_name="$1"
title="$2" title="$2"
fi fi
report_sample.py \ if image_is_not_root; then
--symfs "${SYMBOL_DIR}" \ report_sample.py \
--kallsyms "${SYMBOL_DIR}/kallsyms" \ --symfs "${SYMBOL_DIR}" \
perf.data >out.perf perf.data >out.perf
else
report_sample.py \
--symfs "${SYMBOL_DIR}" \
--kallsyms "${SYMBOL_DIR}/kallsyms" \
perf.data >out.perf
fi
stackcollapse-perf.pl out.perf >out.folded stackcollapse-perf.pl out.perf >out.folded
flamegraph.pl --title="${title}" out.folded >"${file_name}" flamegraph.pl --title="${title}" out.folded >"${file_name}"
rm out.perf rm out.perf
@ -361,18 +361,11 @@ main() {
fi fi
ok "one device is connected via USB" ok "one device is connected via USB"
# Ensure that the device is rooted.
if image_is_not_root; then
error "device is not rooted"
return 1
fi
ok "device is rooted"
# Restart adb with root permissions if needed. # Restart adb with root permissions if needed.
if adb_has_no_root_permissions; then if image_is_root && adb_has_no_root_permissions; then
adb root adb root
ok "adb is running as root"
fi fi
ok "adbd is running as root"
# Create an empty symbol cache in the tmp folder. # Create an empty symbol cache in the tmp folder.
# TODO(henrika): it might not be required to start from a clean cache. # TODO(henrika): it might not be required to start from a clean cache.