profile-chrome-startup.sh 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #!/bin/bash
  2. # Copyright 2018 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. set -e
  6. shopt -s nullglob
  7. shopt -s extglob
  8. function kill_process() {
  9. name=$1
  10. pid=$($adb shell "pidof $name" || true)
  11. if [ ! -z "$pid" ]; then
  12. echo "Killing $name..."
  13. $adb shell "kill $pid"
  14. else
  15. echo "$name is not running."
  16. fi
  17. }
  18. function get_data_file() {
  19. trace_file=$1
  20. extension=$2
  21. echo "${trace_file%.*}.$extension"
  22. }
  23. function get_logcat_file() {
  24. trace_file=$1
  25. get_data_file "$trace_file" "logcat"
  26. }
  27. function get_meminfo_file() {
  28. trace_file=$1
  29. tag=$2
  30. get_data_file "$trace_file" "$tag.meminfo"
  31. }
  32. function analyze_trace_file() {
  33. trace_file=$1
  34. trace_events_to_print=$2
  35. logcat_file="$(get_logcat_file "$trace_file")"
  36. echo "Processes started / died:"
  37. grep -E "Start proc|died|MY-DBG" "$logcat_file"
  38. extractor_arguments="$trace_file"
  39. if [ ! -z "$trace_events_to_print" ]; then
  40. extractor_arguments="$extractor_arguments --print-events=$trace_events_to_print"
  41. fi
  42. "$this_path/systrace-extract-startup.py" $extractor_arguments
  43. }
  44. function analyze_meminfo_file() {
  45. meminfo_file=$1
  46. if [ -f "$meminfo_file" ]; then
  47. echo "$meminfo_file"
  48. grep -A 5 "Total RAM" "$meminfo_file"
  49. fi
  50. }
  51. function capture_analyze_meminfo_file() {
  52. meminfo_file=$1
  53. $adb shell "dumpsys meminfo" > "$meminfo_file"
  54. analyze_meminfo_file "$meminfo_file"
  55. }
  56. function echo_separator() {
  57. s="----------"
  58. echo
  59. echo "$s$s$s$s$s$s$s$s" # 8*10
  60. }
  61. this_path="$(dirname "$0")"
  62. adb="$ADB_PATH"
  63. if [ -z "$adb" ]; then
  64. adb="$(which adb)"
  65. fi
  66. if [ -z "$adb" ]; then
  67. echo "Where's adb? Can't find it."
  68. exit 1
  69. fi
  70. export ADB_PATH="$adb"
  71. output_tag=
  72. browser=chrome
  73. trace_time=10
  74. cold=false
  75. url=
  76. atrace_buffer_size=
  77. atrace_categories=
  78. killg=false
  79. repeat=
  80. analyze=false
  81. meminfo=false
  82. checktabs=false
  83. taburl=
  84. trace_events_to_print=
  85. webapk_package=
  86. for i in "$@"; do
  87. case $i in
  88. --help)
  89. echo "$(basename "$0") output-tag [options]"
  90. exit 0
  91. ;;
  92. --browser=*)
  93. browser="${i#*=}"
  94. ;;
  95. --url=*)
  96. url="${i#*=}"
  97. ;;
  98. --warm)
  99. cold=false
  100. ;;
  101. --cold)
  102. cold=true
  103. ;;
  104. --atrace=*)
  105. atrace_categories="${i#*=}"
  106. ;;
  107. --atrace-buffer-size*)
  108. atrace_buffer_size="${i#*=}"
  109. ;;
  110. --killg)
  111. killg=true
  112. ;;
  113. --trace-time=*)
  114. trace_time="${i#*=}"
  115. ;;
  116. --repeat=*)
  117. repeat="${i#*=}"
  118. ;;
  119. --analyze)
  120. analyze=true
  121. ;;
  122. --meminfo)
  123. meminfo=true
  124. ;;
  125. --checktabs)
  126. checktabs=true
  127. ;;
  128. --taburl=*)
  129. taburl="${i#*=}"
  130. ;;
  131. --print-trace-events=*)
  132. trace_events_to_print="${i#*=}"
  133. ;;
  134. --webapk=*)
  135. webapk_package="${i#*=}"
  136. ;;
  137. --extra_chrome_categories=*)
  138. extra_chrome_categories="${i#*=}"
  139. ;;
  140. --*)
  141. echo "Unknown option or missing option argument: $i"
  142. exit 1
  143. ;;
  144. *)
  145. if [ -z "$output_tag" ]; then
  146. output_tag="$i"
  147. else
  148. echo "Unknown option: $i"
  149. exit 1
  150. fi
  151. ;;
  152. esac
  153. if [ -z "$output_tag" ]; then
  154. echo "First argument must be the output tag."
  155. exit 1
  156. fi
  157. shift
  158. done
  159. if [ -d "$output_tag" ]; then
  160. output_tag="${output_tag%%+(/)}/trace"
  161. fi
  162. specified_output_tag="$output_tag"
  163. if [ $analyze = true ]; then
  164. for file in $output_tag*.html; do
  165. echo_separator
  166. echo "$file"
  167. analyze_meminfo_file "$(get_meminfo_file "$output_file" "before")"
  168. analyze_meminfo_file "$(get_meminfo_file "$output_file" "after")"
  169. echo
  170. analyze_trace_file "$file" "$print_trace_events"
  171. done
  172. exit 0
  173. fi
  174. browser_package=
  175. case $browser in
  176. chrome)
  177. browser_package="com.google.android.apps.chrome"
  178. ;;
  179. canary)
  180. browser_package="com.chrome.canary"
  181. browser="chrome_canary"
  182. ;;
  183. dev)
  184. browser_package="com.chrome.dev"
  185. ;;
  186. beta)
  187. browser_package="com.chrome.beta"
  188. ;;
  189. stable)
  190. browser_package="com.android.chrome"
  191. ;;
  192. chromium)
  193. browser_package="org.chromium.chrome"
  194. ;;
  195. *)
  196. echo "Unknown browser $browser"
  197. exit 1
  198. esac
  199. profile_options=
  200. profile_options="$profile_options --browser=$browser"
  201. if [ ! "$browser" = "chrome" ]; then
  202. output_tag="$output_tag-$browser"
  203. fi
  204. profile_options="$profile_options --time=$trace_time"
  205. if [ ! -z "$atrace_categories" ]; then
  206. profile_options="$profile_options --atrace-categories=$atrace_categories"
  207. output_tag="$output_tag-${atrace_categories//,/_}"
  208. fi
  209. if [ ! -z "$atrace_buffer_size" ]; then
  210. profile_options="$profile_options --atrace-buffer-size=$atrace_buffer_size"
  211. output_tag="$output_tag-${atrace_buffer_size}"
  212. fi
  213. if [ $cold = true ]; then
  214. profile_options="$profile_options --cold"
  215. output_tag="$output_tag-cold"
  216. fi
  217. profile_options="$profile_options --url=$url"
  218. if [ ! -z "$url" ]; then
  219. output_tag="$output_tag-url"
  220. fi
  221. if [ ! -z "$webapk_package" ]; then
  222. output_tag="$output_tag-webapk"
  223. profile_options="$profile_options --webapk-package=$webapk_package"
  224. fi
  225. if [ $killg = true ]; then
  226. output_tag="$output_tag-killg"
  227. fi
  228. # Must be last for ease of globbing.
  229. output_tag="$output_tag-${trace_time}s"
  230. if [ $checktabs = true ] || [ $killg = true ] || [ ! -z "$taburl" ]; then
  231. $adb root > /dev/null
  232. fi
  233. # Make sure Chrome can write the trace file.
  234. # These commands may fail with a security exception on some Android devices that
  235. # don't allow changing permissions. Chrome likely already has these permissions
  236. # so the script should still work.
  237. $adb shell "pm grant $browser_package \
  238. android.permission.READ_EXTERNAL_STORAGE" || true
  239. $adb shell "pm grant $browser_package \
  240. android.permission.WRITE_EXTERNAL_STORAGE" || true
  241. if [ ! -z "$taburl" ]; then
  242. echo "Opening $taburl in a single tab..."
  243. $adb shell "am force-stop $browser_package"
  244. $adb shell "rm -f /data/data/$browser_package/app_tabs/0/tab*"
  245. $adb shell "am start -a android.intent.action.VIEW \
  246. -n $browser_package/org.chromium.chrome.browser.ChromeTabbedActivity \
  247. -d $taburl"
  248. sleep 5
  249. $adb shell "am start -a android.intent.action.MAIN -c android.intent.category.HOME"
  250. sleep 1
  251. $adb shell "am force-stop $browser_package"
  252. echo
  253. fi
  254. repeat_count=1
  255. if [ ! -z "$repeat" ]; then
  256. repeat_count="$repeat"
  257. fi
  258. if [ ! -z "$extra_chrome_categories" ]; then
  259. chrome_categories="_DEFAULT_CHROME_CATEGORIES,${extra_chrome_categories}"
  260. profile_options="$profile_options --chrome_categories=${chrome_categories}"
  261. fi
  262. first_iteration=true
  263. for iteration in $(seq "$repeat_count"); do
  264. if [ $first_iteration = true ]; then
  265. first_iteration=false
  266. else
  267. echo_separator
  268. sleep 2
  269. fi
  270. if [ $killg = true ]; then
  271. echo "Preemptively killing g* processes..."
  272. $adb logcat -c
  273. kill_process "com.google.process.gapps"
  274. kill_process "com.google.android.gms"
  275. sleep 1
  276. $adb logcat -d | grep -E "Start proc|died" || true
  277. fi
  278. echo
  279. if [ -z "$repeat" ]; then
  280. output_file="$output_tag.html"
  281. if [ -f "$output_file" ]; then
  282. for i in {2..1000}; do
  283. output_file="$output_tag~$i.html"
  284. if [ ! -f "$output_file" ]; then
  285. break;
  286. fi
  287. done
  288. fi
  289. if [ -f "$output_file" ]; then
  290. echo "Failed to find unoccupied output file. Last was: $output_file"
  291. exit 1
  292. fi
  293. else
  294. output_file="$output_tag~${repeat_count}_$iteration.html"
  295. if [ -f "$output_file" ]; then
  296. echo "Output file already exists: $output_file"
  297. echo "Please add something unique to the tag ($specified_output_tag)."
  298. exit 1
  299. fi
  300. fi
  301. echo "Output file: $output_file"
  302. logcat_file="$(get_logcat_file "$output_file")"
  303. echo "Logcat output file: $logcat_file"
  304. if [ $meminfo = true ]; then
  305. echo
  306. capture_analyze_meminfo_file "$(get_meminfo_file "$output_file" "before")"
  307. fi
  308. echo
  309. echo "Profiling with options: $profile_options"
  310. ./build/android/adb_profile_chrome_startup \
  311. $profile_options \
  312. "--output=$output_file"
  313. if [ $meminfo = true ]; then
  314. echo
  315. capture_analyze_meminfo_file "$(get_meminfo_file "$output_file" "after")"
  316. fi
  317. $adb shell "am force-stop $browser_package"
  318. $adb shell "killall logcat" > /dev/null 2>&1 || true
  319. $adb logcat -d > "${logcat_file}"
  320. rm -f chrome-profile-results-*
  321. $adb shell "rm -f /sdcard/Download/chrome-profile-results-*"
  322. echo
  323. analyze_trace_file "$output_file" "$trace_events_to_print"
  324. if [ $checktabs = true ]; then
  325. # Yields empty string when value is -1
  326. active_tab_id="$( \
  327. $adb shell "cat /data/data/$browser_package/shared_prefs/${browser_package}_preferences.xml" \
  328. | sed -n 's/^.*ACTIVE_TAB_ID" value="\([0-9]\{1,3\}\).*$/\1/p')"
  329. # Yields empty string when there is no 'tab' file
  330. tab_id="$( \
  331. $adb shell ls /data/data/$browser_package/app_tabs/0 \
  332. | sed -n 's/tab\([0-9]\{1,3\}\)\s*/\1/p')"
  333. if [ "$active_tab_id" != "$tab_id" ]; then
  334. echo "Tab IDs don't match (active_tab_id=$active_tab_id, tab_id=$tab_id), last result is not reliable."
  335. exit 1
  336. fi
  337. fi
  338. done