OSDN Git Service

app-launcher is a App Launch Perf Analysis tool.
[android-x86/system-extras.git] / app-launcher / app-launcher
1 #!/bin/sh
2
3 parseoptions() {
4     verbose=false
5     user_experience=false
6     little_cores_off=false
7     iterations=0
8     pagecached=false
9
10     while [ $# -gt 1 ]
11     do
12         case $1 in
13             -a)
14                 ;;
15             -b)
16                 little_cores_off=true
17                 ;;
18             -c)
19                 pagecached=true
20                 ;;
21             -h)
22                 usage
23                 ;;
24             -u)
25                 user_experience=true
26                 ;;
27             -v)
28                 verbose=true
29                 ;;
30             *)
31                 usage
32                 ;;
33             esac
34         shift
35     done
36
37     iterations=$1
38     if [ $iterations -lt 100 ]; then
39         usage
40     fi
41 }
42
43 getstats () {
44     infile=$1
45     app=$2
46     echo "Data for $app :"
47
48     # Chrome related Hack alert :
49     # For Chrome launches, "TotalTime" is the right metric to measure. That is closer
50     # to what the user seems Chrome launch time as. So special case Chrome here.
51
52     if [ $app == Chrome ]; then
53         launch_time_string="TotalTime"
54     else
55         launch_time_string="ThisTime"
56     fi
57
58     # From Activity Manager
59     echo "Launch Time :"
60     fgrep $launch_time_string $infile | awk '{print $2}' | computestats
61
62     # Data from simpleperf
63     echo "cpu-cycles :"
64     fgrep cpu-cycles $infile | awk '{print $1}' | sed s/,//g | computestats
65
66     # CPU util% Data from /proc/stat
67     echo "cpu-util% :"
68     fgrep 'Total CPU util' $infile | awk '{print $5}' | computestatsf
69     echo "user-cpu-util% :"
70     fgrep 'User CPU util' $infile | awk '{print $5}' | computestatsf
71     echo "sys-cpu-util% (incl hardirq/softirq) :"
72     fgrep 'Sys CPU util' $infile | awk '{print $5}' | computestatsf
73
74     if [ $verbose == true ]; then
75         echo "instructions : "
76         fgrep instructions $infile | awk '{print $1}' | sed s/,//g | computestats
77
78         echo "cycles per instruction : "
79         fgrep instructions $infile | awk '{print $4}' | sed s/,//g | computestatsf
80
81         echo "branch-misses : "
82         fgrep branch-misses $infile | awk '{print $1}' | sed s/,//g | computestats
83
84         echo "context-switches : "
85         fgrep context-switches $infile | awk '{print $1}' | sed s/,//g | computestats
86
87         echo "page-faults : "
88         fgrep page-faults $infile | awk '{print $1}' | sed s/,//g | computestats
89     fi
90
91     if [ $system_bdev_set == true ]; then
92         # (Storage) Data from /proc we've collected
93         echo "KB read for $system_block_device blkdev :"
94         fgrep KB $infile | grep system | awk '{print $5}' | computestats
95
96         echo "iowait% :"
97         fgrep IOwait $infile | awk '{print $3}' | computestatsf
98
99         echo "Device util% for $system_block_device blkdev :"
100         fgrep 'Device util' $infile | awk '{print $4}' | computestatsf
101     fi
102 }
103
104 cpufreq_volantis() {
105     echo "Setting Governor to performance"
106     if [ $little_cores_off == true ]; then
107         echo "Cannot turn off Little cores on $model"
108         exit 1
109     fi
110     i=0
111     num_cores=2
112     while [ $i -lt  $num_cores ]
113     do
114         adb shell "echo performance  > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_g\
115 overnor"
116         adb shell "echo 2499000 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_fr\
117 eq"
118         i=`expr $i + 1`
119     done
120     # Lock the GPU frequencies
121     echo -n 852000000 > /d/clock/override.gbus/rate
122     echo -n 1 > /d/clock/override.gbus/state
123 }
124
125 cpufreq_fugu() {
126     echo "Setting Governor to performance"
127     if [ $little_cores_off == true ]; then
128         echo "Cannot turn off Little cores on $model"
129         exit 1
130     fi
131     i=0
132     num_cores=4
133     while [ $i -lt  $num_cores ]
134     do
135         adb shell "echo performance  > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
136         adb shell "echo 1833000 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
137         i=`expr $i + 1`
138     done
139 }
140
141 cpufreq_marlin_sailfish () {
142     echo "Setting Governor to performance"
143     # GPU Governor and Frequency
144     adb shell 'echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor'
145     adb shell 'echo 624000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq'
146     if [ $little_cores_off == true ]; then
147         # Disable Little Cores, force app to run on big cores
148         echo "Disabling Little Cores"
149         adb shell 'echo 0 > /sys/devices/system/cpu/cpu0/online'
150         adb shell 'echo 0 > /sys/devices/system/cpu/cpu1/online'
151     else
152         echo "Enabling All Cores"
153         adb shell 'echo 1 > /sys/devices/system/cpu/cpu0/online'
154         adb shell 'echo 1 > /sys/devices/system/cpu/cpu1/online'
155         adb shell 'echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
156         adb shell 'echo 1996800 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq'
157         # cpu1 needed ?
158         adb shell 'echo performance > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor'
159         adb shell 'echo 1996800 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq'
160     fi
161     # Set Governor to performance, up scaling_max_frequency to highest
162     adb shell 'echo performance  > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor'
163     # Only necessary to set max_freq on cpu2, cpu3 is in same cluster and will
164     # automatically get the same settings
165     adb shell 'echo 2150400 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq'
166 }
167
168 cpufreq_angler () {
169     echo "Setting Governor and Frequency"
170     # GPU Governor and Frequency
171     adb shell "echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor"
172     adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split"
173     adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on"
174     adb shell "echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer"
175     if [ $little_cores_off == true ]; then
176         # Disable Little Cores, force app to run on big cores
177         echo "Disabling Little Cores"
178         i=0
179         num_cores=4
180         while [ $i -lt $num_cores ]
181         do
182             adb shell "echo 0 > /sys/devices/system/cpu/cpu$i/online"
183             i=`expr $i + 1`
184         done
185     else
186         echo "Enabling All Cores"
187         # Enable Little cores here, set governor to performance
188         # Lock frequency of little cores
189         i=0
190         num_cores=4
191         while [ $i -lt $num_cores ]
192         do
193             adb shell "echo 1 > /sys/devices/system/cpu/cpu$i/online"
194             adb shell "echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
195             # Lock frequency of little cores
196             adb shell "echo 1555200 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
197             i=`expr $i + 1`
198         done
199     fi
200     i=4
201     num_cores=8
202     while [ $i -lt $num_cores ]
203     do
204         adb shell "echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
205         # Lock frequency of big cores
206         adb shell "echo 1958400 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
207         i=`expr $i + 1`
208     done
209 }
210
211 #
212 # This strange bit of logic is needed to get the underlying block devices for /system
213 # for Marlin/Sailfish
214 #
215 get_marlin_sailfish_devnames () {
216     # This bit of code required to get the block dev for /system and /vendor
217     # Suffix can be _a or _b, depending on what the active /system partition is
218 #    suffix=`adb shell getprop ro.boot.slot_suffix`
219     # Get the blockdevice using the suffix we got above
220 #    system_block_device=`adb shell ls -l /dev/block/platform/soc/*ufs*/by-name/system$suffix | awk '{ print $10 }' `
221     # Vendor is more straightforward, but we don't use it right now
222 #    vendor_block_device=`adb shell df /vendor | grep -v Filesystem | awk '{print $1}' `
223     # finally extract the last component of the absolute device pathname we got above
224 #    system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
225 #    vendor_block_device=`echo $vendor_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
226     system_bdev_set=true
227 #   For now, hardcode sda for Marlin/Sailfish block device
228 #   XXX - We'll get stats for entire device
229     system_block_device=sda
230     echo Block Device $system_block_device
231 }
232
233 get_angler_devnames () {
234     # Get the underlying bdev from the "by-name" mapping
235     system_block_device=`adb shell 'find /dev/block/platform -name by-name | xargs ls -l' | grep system | awk '{ print $10 }' `
236     # extract the last component of the absolute device pathname we got above
237     system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
238     # vendor is unused right now, but get the bdev anyway in case we decide to use it
239     # Get the underlying bdev from the "by-name" mapping
240     vendor_block_device=`adb shell 'find /dev/block/platform -name by-name | xargs ls -l' | grep vendor | awk '{ print $10 }' `
241     # extract the last component of the absolute device pathname we got above
242    vendor_block_device=`echo $vendor_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
243    system_bdev_set=true
244 }
245
246 get_fugu_devnames () {
247     system_block_device=`adb shell ls -l /dev/block/by-name/system | awk '{ print $10 }' `
248     system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
249     system_bdev_set=true
250 }
251
252 get_volantis_devnames () {
253     # Hardcoding all of the mmcblk0 device for now
254     system_block_device=mmcblk0
255     system_bdev_set=true
256 }
257
258 system_stats_before() {
259     if [ $system_bdev_set == true ]; then
260         # Get BEFORE read stats for /system
261         adb shell 'cat /proc/diskstats' | grep -w $system_block_device > /tmp/$model-system
262         BEFORE_RD_IOS_SYSTEM=`awk '{ print $4 }' /tmp/$model-system`
263         BEFORE_RD_SECTORS_SYSTEM=`awk '{ print $6 }' /tmp/$model-system`
264         # iowait% computation
265         adb shell 'cat /proc/stat' | grep -w cpu > /tmp/procstat
266         user_ticks_before=`awk '{ print ($2 + $3) }' /tmp/procstat`
267         sys_ticks_before=`awk '{ print ($4 + $7 + $8) }' /tmp/procstat`
268         cpubusy_ticks_before=`awk '{ print ($2 + $3 + $4 + $7 + $8) }' /tmp/procstat`
269         iowait_ticks_before=`awk '{ print $6 }' /tmp/procstat`
270         total_ticks_before=`awk '{ print ($2 + $3 + $4 + $5 + $7 + $8) }' /tmp/procstat`
271         # Device util% computation
272         # Note hz=100, so multiplying uptime (in seconds) by 100, gives us
273         # the uptime in hz.
274         adb shell 'cat /proc/uptime' > /tmp/uptime
275         uptime_before_hz=`awk '{ print ($1 * 100) }' /tmp/uptime`
276         # Note that the device (busy) ticks is in ms. Since hz=100, dividing
277         # device (busy) ticks by 10, gives us this in the correct ticks units
278         device_util_before_hz=`awk '{ print ($13 / 10) }' /tmp/$model-system`
279     fi
280 }
281
282 system_stats_after() {
283     if [ $system_bdev_set == true ]; then
284         # Get AFTER read stats for /system
285         adb shell 'cat /proc/diskstats' | grep -w $system_block_device > /tmp/$model-system
286         AFTER_RD_IOS_SYSTEM=`awk '{ print $4 }' /tmp/$model-system`
287         AFTER_RD_SECTORS_SYSTEM=`awk '{ print $6 }' /tmp/$model-system`
288         # iowait% computation
289         adb shell 'cat /proc/stat' | grep -w cpu > /tmp/procstat
290         user_ticks_after=`awk '{ print ($2 + $3) }' /tmp/procstat`
291         sys_ticks_after=`awk '{ print ($4 + $7 + $8) }' /tmp/procstat`
292         cpubusy_ticks_after=`awk '{ print ($2 + $3 + $4 + $7 + $8) }' /tmp/procstat`
293         iowait_ticks_after=`awk '{ print $6 }' /tmp/procstat`
294         total_ticks_after=`awk '{ print ($2 + $3 + $4 + $5 + $7 + $8) }' /tmp/procstat`
295         # Device util% computation
296         # Note hz=100, so multiplying uptime (in seconds) by 100, gives us
297         # the uptime in hz.
298         adb shell 'cat /proc/uptime' > /tmp/uptime
299         uptime_after_hz=`awk '{ print ($1 * 100) }' /tmp/uptime`
300         # Note that the device (busy) ticks is in ms. Since hz=100, dividing
301         # device (busy) ticks by 10, gives us this in the correct ticks units
302         device_util_after_hz=`awk '{ print ($13 / 10) }' /tmp/$model-system`
303     fi
304 }
305
306 system_stats_delta() {
307     if [ $system_bdev_set == true ]; then
308         # Sectors to KB
309         READ_KB_SYSTEM=`expr $AFTER_RD_SECTORS_SYSTEM - $BEFORE_RD_SECTORS_SYSTEM`
310         READ_KB_SYSTEM=`expr $READ_KB_SYSTEM / 2`
311         echo Read IOs /system = `expr $AFTER_RD_IOS_SYSTEM - $BEFORE_RD_IOS_SYSTEM`
312         echo Read KB /system = $READ_KB_SYSTEM
313         echo $iowait_ticks_before $iowait_ticks_after $total_ticks_before $total_ticks_after | awk '{ printf "IOwait = %.2f\n", (($2 - $1) * 100.0) / ($4 - $3) }'
314         echo $device_util_before_hz $device_util_after_hz $uptime_before_hz $uptime_after_hz | awk '{ printf "Device util% = %.2f\n", (($2 - $1) * 100.0) / ($4 - $3) }'
315         echo $user_ticks_after $user_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "User CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
316         echo $sys_ticks_after $sys_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "Sys CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
317         echo $cpubusy_ticks_after $cpubusy_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "Total CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
318     fi
319 }
320
321 launch_app() {
322     package=$1
323     activity=$2
324     adb shell "am force-stop $package"
325     sleep 1
326
327     i=0
328     while [ $i -lt $iterations ]
329     do
330         if [ $pagecached == false ]; then
331             adb shell 'echo 3 > /proc/sys/vm/drop_caches'
332         fi
333         # The -W argument to am start forces am start to wait till the launch completes.
334         # The -S argument forces it to kill any existing app that is running first
335         # eg. adb shell 'am start -W -S -n com.android.chrome/com.google.android.apps.chrome.Main'
336         system_stats_before
337         adb shell "simpleperf stat -a am start -W -n $package/$activity"
338         system_stats_after
339         system_stats_delta
340         sleep 1
341         adb shell "am force-stop $package"
342         sleep 1
343         i=`expr $i + 1`
344     done
345 }
346
347 launch_fugu_apps() {
348     launch_app com.google.android.youtube.tv com.google.android.apps.youtube.tv.activity.TvGuideActivity > youtube-$model
349     getstats youtube-$model YouTube
350     launch_app com.google.android.play.games com.google.android.gms.games.pano.activity.PanoGamesOnboardHostActivity > games-$model
351     getstats games-$model Games
352     launch_app com.google.android.music com.android.music.activitymanagement.TopLevelActivity > music-$model
353     getstats music-$model Music
354 }
355
356 launch_phone_apps() {
357     launch_app com.android.chrome com.google.android.apps.chrome.Main > chrome-$model
358     getstats chrome-$model Chrome
359     launch_app com.google.android.GoogleCamera com.android.camera.CameraActivity > camera-$model
360     getstats camera-$model Camera
361     launch_app com.google.android.apps.maps com.google.android.maps.MapsActivity > maps-$model
362     getstats maps-$model Maps
363 #   launch_app com.google.android.youtube com.google.android.apps.youtube.app.WatchWhileActivity > youtube-$model
364 #   getstats youtube-$model YouTube
365 }
366
367 usage() {
368     echo 'Usage: app-launcher [-c|-v] -a|-b|-u num-iterations'
369     echo 'where num-iterations >= 100'
370     echo '-v (optional) for verbose stats dump'
371     echo '-a|-b|-u required:'
372     echo '        -a:all cores'
373     echo '        -b:only big cores'
374     echo '        -c:pagecached. Do not drop pagecache before each launch (not default)'
375     echo '        -h:Dump this help menu'
376     echo '        -u:user experience, no change to cpu/gpu frequencies or governors'
377     echo '        -a/-b locks CPU/GPU freqs to max, performance governor, thermal/perfd off'
378     echo '        -u runs with default device configs, as users would see it'
379     exit 1
380 }
381
382 #
383 # The main() part of the script follows :
384 #
385
386 if [ $# -lt 2 ]; then
387     usage
388 fi
389
390 which computestats > /dev/null
391 if [ $? != 0 ]; then
392     echo "ERROR: Please add computestats utiliy to your PATH"
393     exit 1
394 fi
395
396 which computestatsf > /dev/null
397 if [ $? != 0 ]; then
398     echo "Error: Please add computestatsf utility to your PATH"
399     exit 1
400 fi
401
402 parseoptions $@
403
404 adb root && sleep 2
405
406 if [ $user_experience == false ]; then
407     # Important to stop the thermal-engine to prevent throttling while test is running
408     # and stop perfd
409     adb shell 'stop thermal-engine'
410     adb shell 'stop perfd'
411 else
412     echo "User Experience: Default Configs. No changes to cpufreq settings"
413 fi
414
415 model=`adb shell getprop ro.product.name`
416 # Releases are inconsistent with various trailing characters, remove them all
417 model=`echo $model | sed 's/[ \t\r\n]*$//' `
418
419 echo Found $model Device
420
421 system_bdev_set=false
422 case $model in
423     marlin | sailfish)
424         if [ $user_experience == false ]; then
425             cpufreq_marlin_sailfish
426         fi
427         get_marlin_sailfish_devnames
428         ;;
429     angler)
430         if [ $user_experience == false ]; then
431             cpufreq_angler
432         fi
433         get_angler_devnames
434         ;;
435     fugu)
436         if [ $user_experience == false ]; then
437             cpufreq_fugu
438         fi
439         get_fugu_devnames
440         ;;
441     volantis | volantisg)
442         if [ $user_experience == false ]; then
443             cpufreq_volantis
444         fi
445         get_volantis_devnames
446         ;;
447     *)
448         echo Unknown Device $model
449         exit 1
450         ;;
451 esac
452
453
454 #
455 # launch each app in turn
456 #
457 if [ $model == "fugu" ]; then
458     launch_fugu_apps
459 else # Phone Apps
460     launch_phone_apps
461 fi