diff options
author | Todd Kjos <tkjos@google.com> | 2015-05-20 12:47:00 -0700 |
---|---|---|
committer | Todd Kjos <tkjos@google.com> | 2015-05-20 12:51:26 -0700 |
commit | 684f65f8602d1e1a79170984acc18421fb8f4c98 (patch) | |
tree | 1b1f84a8601323ea66e3bce0e3b3fd4d1c7ab8fb | |
parent | 1865679fda9bd1e12bc583268537bccc4e4a43bc (diff) | |
download | extras-684f65f8602d1e1a79170984acc18421fb8f4c98.tar.gz |
Scripts to automate simple workloads for testing
DO NOT MERGE (already in master)
The initial set of scripts:
recentsfling.sh : start a set of apps, switch to recents and fling
systemapps.sh : start a set of apps, and then loop to move them
to the forground, checking whether the app had
been LMK'd or required direct reclaims
feedly-chrome.sh : automate a feedly, chrome
workflow making sure both stay in memory
Change-Id: I40f0862623ea0963bb0eaed3a585b41b69bbbbc7
-rw-r--r-- | tests/workloads/atrace-uncompress.py | 35 | ||||
-rwxr-xr-x | tests/workloads/capture.sh | 62 | ||||
-rwxr-xr-x | tests/workloads/defs.sh | 434 | ||||
-rwxr-xr-x | tests/workloads/feedly-chrome.sh | 111 | ||||
-rwxr-xr-x | tests/workloads/recentfling.sh | 132 | ||||
-rwxr-xr-x | tests/workloads/systemapps.sh | 212 |
6 files changed, 986 insertions, 0 deletions
diff --git a/tests/workloads/atrace-uncompress.py b/tests/workloads/atrace-uncompress.py new file mode 100644 index 00000000..5efb6982 --- /dev/null +++ b/tests/workloads/atrace-uncompress.py @@ -0,0 +1,35 @@ +# +# Uncompress a file generated via atrace -z +# +# Usage: python atrace-uncompress.py infile > outfile +# +import sys, zlib + +def main(): + + if len(sys.argv) != 2: + print >> sys.stderr, ('Usage: %s inputfile' % sys.argv[0]) + sys.exit(1) + + infile = open(sys.argv[1], "rb") + out = infile.read() + parts = out.split('\nTRACE:', 1) + + data = ''.join(parts[1]) + + # Remove CR characters + if data.startswith('\r\n'): + data = data.replace('\r\n', '\n') + + # Skip the initial newline. + data = data[1:] + + if not data: + print >> sys.stderr, ('No trace data found') + sys.exit(1) + + out = zlib.decompress(data) + print(out) + +if __name__ == '__main__': + main() diff --git a/tests/workloads/capture.sh b/tests/workloads/capture.sh new file mode 100755 index 00000000..721fe8c8 --- /dev/null +++ b/tests/workloads/capture.sh @@ -0,0 +1,62 @@ +# Capture and display input events and coordinates +# +# Usage: ./capture.sh +# + +# do a throw-away adb in case the server is out-of-date +adb devices -l 2>&1 >/dev/null +devInfo=$(adb devices -l | grep -v ^List | head -1) + +set -- $devInfo +echo devInfo=$devInfo + +DEVICE=$(echo $4 | sed 's/product://') + +function convert { + in=$1 + max=$2 + scale=$3 + if [ $max -eq 0 ]; then + echo $in + else + ((out=in*scale/max)) + echo $out + fi +} + + +case $DEVICE in +(shamu|hammerhead) + # no scaling necessary + xmax=0 + ymax=0;; +(volantis) + xmax=3060 + xscale=1500 + ymax=2304 + yscale=1950;; +(*) + echo "Error: No display information available for $DEVICE" + exit 1;; +esac + +echo Capturing input for $DEVICE... +stdbuf -o0 adb shell getevent -t | + stdbuf -o0 grep "event.: 0003" | + stdbuf -o0 grep "0003 003[0156a9]" | + stdbuf -o0 tr ':[]
' ' ' | while read line +do + set -- $line + code=$4 + value=$((16#$5)) + case $code in + (0035) x=$(convert $value $xmax $xscale);; + (0036) y=$(convert $value $ymax $yscale);; + (0030) tag="majorTouch";; + (0031) tag="minorTouch";; + (003a) tag="pressure";; + (0039) tag="trackingId";; + (--) echo unknown code=$code;; + esac + printf "%-10s %-4d %-4d\n" $tag $x $y +done diff --git a/tests/workloads/defs.sh b/tests/workloads/defs.sh new file mode 100755 index 00000000..838d04f4 --- /dev/null +++ b/tests/workloads/defs.sh @@ -0,0 +1,434 @@ +# functions and definitions for workload automation scripts +# +# See recentfling.sh, systemapps.sh, and other scripts that use +# these definitions. +# + +dflttracecategories="gfx input view am rs power sched freq idle load memreclaim" +dfltAppList="gmail hangouts chrome youtube camera photos play maps calendar earth calculator sheets docs home" +generateActivities=0 + +# default activities. Can dynamically generate with -g. +gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail' +hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity' +chromeActivity='com.android.chrome/com.google.android.apps.chrome.ChromeTabbedActivity' +chromeLActivity='com.android.chrome/com.google.android.apps.chrome.document.DocumentActivity' +youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity' +cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity' +playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity' +feedlyActivity='com.devhd.feedly/com.devhd.feedly.Main' +photosActivity='com.google.android.apps.plus/com.google.android.apps.photos.phone.PhotosHomeActivity' +mapsActivity='com.google.android.apps.maps/com.google.android.maps.MapsActivity' +calendarActivity='com.google.android.calendar/com.android.calendar.AllInOneActivity' +earthActivity='com.google.earth/com.google.earth.EarthActivity' +calculatorActivity='com.android.calculator2/com.android.calculator2.Calculator' +sheetsActivity='com.google.android.apps.docs.editors.sheets/com.google.android.apps.docs.app.NewMainProxyActivity' +docsActivity='com.google.android.apps.docs.editors.docs/com.google.android.apps.docs.app.NewMainProxyActivity' +operaActivity='com.opera.mini.native/com.opera.mini.android.Browser' +firefoxActivity='org.mozilla.firefox/org.mozilla.firefox.App' +homeActivity='com.google.android.googlequicksearchbox/com.google.android.launcher.GEL' + +function showUsage { + echo "$0: unrecognized option: $1" + echo; echo "Usage: $0 [options]" + echo "-e : stop on error" + echo "-i iterations" + echo "-n : keep trace files" + echo "-o output file" + echo "-s device : adb device" + echo "-t trace categories" + echo "-g : generate activity strings" +} + +DEVICE=unknown + +# handle args +while [ $# -gt 0 ] +do + case "$1" in + (-d) DEVICE=$2; shift;; + (-e) stoponerror=1;; + (-n) savetmpfiles=1;; + (-t) tracecategories=$2; shift;; + (-i) iterations=$2; shift;; + (-o) output=$2; shift;; + (-v) verbose=1;; + (-nz) compress=0;; + (-s) deviceName=$2; shift;; + (-g) generateActivities=1;; + (--) ;; + (*) + chk1=$(functions 2>/dev/null) + chk2=$(typeset -F 2>/dev/null) + + if echo $chk1 $chk2 | grep -q processLocalOption; then + if ! processLocalOption "$1" "$2"; then + shift + fi + else + showUsage $1 + exit 1 + fi;; + esac + shift +done + +# check if running on a device +if ls /etc/* 2>/dev/null | grep -q android.hardware; then + ADB="" + compress=0 + isOnDevice=1 +else + # do a throw-away adb in case the server is out-of-date + adb devices -l 2>&1 >/dev/null + + if [ -z "$deviceName" ]; then + devInfo=$(adb devices -l | grep -v ^List | head -1) + else + devInfo=$(adb devices -l | grep $deviceName) + fi + set -- $devInfo + if [ -z $1 ]; then + echo Error: could not find device $deviceName + exit 1 + fi + deviceName=$1 + ADB="adb -s $deviceName shell " + DEVICE=$(echo $4 | sed 's/product://') + isOnDevice=0 +fi + +# default values if not set by options or calling script +appList=${appList:=$dfltAppList} +savetmpfiles=${savetmpfiles:=0} +stoponerror=${stoponerror:=0} +verbose=${verbose:=0} +compress=${compress:=1} +iterations=${iterations:=5} +tracecategories=${tracecategories:=$dflttracecategories} +ADB=${ADB:=""} +output=${output:="./out"} + +# clear the output file +> $output + +# ADB commands +AM_FORCE_START="${ADB}am start -W -S" +AM_START="${ADB}am start -W" +AM_START_NOWAIT="${ADB}am start" +AM_STOP="${ADB}am force-stop" +AM_LIST="${ADB}am stack list" +WHO="${ADB}whoami" +INPUT="${ADB}input" +PS="${ADB}ps" + +function vout { + # debug output enabled by -v + if [ $verbose -gt 0 ]; then + echo DEBUG: $* >&2 + echo DEBUG: $* >&2 >> $output + fi +} + +function findtimestamp { + # extract timestamp from atrace log entry + while [ "$2" != "" -a "$2" != "tracing_mark_write" ] + do + shift + done + echo $1 +} + +function computeTimeDiff { + # Compute time diff given: startSeconds startNs endSeconds endNS + + # strip leading zeros + startS=$(expr 0 + $1) + endS=$(expr 0 + $3) + if [ "$2" = N ]; then + startNs=0 + endNs=0 + else + startNs=$(expr 0 + $2) + endNs=$(expr 0 + $4) + fi + + ((startMs=startS*1000 + startNs/1000000)) + ((endMs=endS*1000 + endNs/1000000)) + ((diff=endMs-startMs)) + echo $diff +} + +function log2msec { + in=$1 + in=${in:=0.0} + set -- $(echo $in | tr . " ") + # shell addition via (( )) doesn't like leading zeroes in msecs + # field so remove leading zeroes + msecfield=$(expr 0 + $2) + + ((msec=$1*1000000+msecfield)) + ((msec=msec/1000)) + echo $msec +} + +function getStartTime { + # extract event indicating beginning of start sequence + # a) look for a "launching" event indicating start from scratch + # b) look for another activity getting a pause event + _app=$1 + traceout=$2 + ret=0 + s=$(grep "Binder.*tracing_mark_write.*launching" $traceout 2>/dev/null | head -1| tr [\(\)\[\]
:] " ") + if [ -z "$s" ]; then + s=$(grep activityPause $traceout | head -1 2>/dev/null| tr [\(\)\[\]
:] " ") + else + vout $_app was restarted! + ret=1 + fi + vout STARTLOG: $s + log2msec $(findtimestamp $s) + return $ret +} + +function getEndTime { + # extract event indicating end of start sequence. We use the + # first surfaceflinger event associated with the target activity + _app=$1 + traceout=$2 + f=$(grep "surfaceflinger.*tracing_mark_write.*$_app" $traceout 2>/dev/null | + grep -v Starting | head -1 | tr [\(\)\[\]
:] " ") + if [ -z "$f" ]; then + # Hmm. sf symbols may not be there... get the pid + pid=$(${ADB}pidof /system/bin/surfaceflinger | tr "[
]" "[ ]") + f=$(grep " <...>-$pid.*tracing_mark_write.*$_app" $traceout 2>/dev/null | + grep -v Starting | head -1 | tr [\(\)\[\]
:] " ") + fi + vout ENDLOG: $f + log2msec $(findtimestamp $f) +} + +function resetJankyFrames { + ${ADB}dumpsys gfxinfo $1 reset 2>&1 >/dev/null +} + +function getJankyFrames { + if [ -z "$ADB" ]; then + # Note: no awk or sed on devices so have to do this + # purely with bash + total=0 + janky=0 + /system/bin/dumpsys gfxinfo | grep " frames" | while read line + do + if echo $line | grep -q "Total frames"; then + set -- $line + ((total=total+$4)) + elif echo $line | grep -q "Janky frames"; then + set -- $line + ((janky=janky+$3)) + fi + # Note: no tail, awk, or sed on 5.x so get final + # sum via most recently written file + echo $total $janky > ./janky.$$ + done + cat ./janky.$$ + rm -f ./janky.$$ + else + ${ADB}dumpsys gfxinfo $1 | sed -e 's/
//' | awk ' + BEGIN { total=0; janky=0; } + /Total frames/ { total+=$4; } + /Janky frames/ { janky+=$3; } + END { printf "%d %d\n", total, janky; }' + fi +} + +function checkForDirectReclaim { + # look for any reclaim events in atrace output + _app=$1 + traceout=$2 + if grep -qi reclaim $traceout; then + return 1 + fi + return 0 +} + +function startInstramentation { + # Called at beginning of loop. Turn on instramentation like atrace + vout start instramentation $(date) + echo =============================== >> $output + echo Before iteration >> $output + echo =============================== >> $output + ${ADB}cat /proc/meminfo 2>&1 >> $output + ${ADB}dumpsys meminfo 2>&1 >> $output + if [ "$user" = root ]; then + vout ${ADB}atrace -b 32768 --async_start $tracecategories + ${ADB}atrace -b 32768 --async_start $tracecategories >> $output + echo >> $output + fi +} + +function stopInstramentation { + if [ "$user" = root ]; then + vout ${ADB}atrace --async_stop + ${ADB}atrace --async_stop > /dev/null + fi +} + +function stopAndDumpInstramentation { + # Called at beginning of loop. Turn on instramentation like atrace + vout stop instramentation $(date) + echo =============================== >> $output + echo After iteration >> $output + echo =============================== >> $output + ${ADB}cat /proc/meminfo 2>&1 >> $output + ${ADB}dumpsys meminfo 2>&1 >> $output + if [ "$user" = root ]; then + traceout=$1 + traceout=${traceout:=$output} + echo =============================== >> $traceout + echo TRACE >> $traceout + echo =============================== >> $traceout + if [ $compress -gt 0 ]; then + tmpTrace=./tmptrace.$$ + UNCOMPRESS=$CMDDIR/atrace-uncompress.py + > $tmpTrace + zarg="-z" + ${ADB}atrace -z -b 32768 --async_dump >> $tmpTrace + python $UNCOMPRESS $tmpTrace >> $traceout + rm -f $tmpTrace + else + ${ADB}atrace $zarg -b 32768 --async_dump >> $traceout + fi + vout ${ADB}atrace $zarg --async_dump + vout ${ADB}atrace --async_stop + ${ADB}atrace --async_stop > /dev/null + fi +} + +function getActivityName { + cmd="actName=\$${1}Activity" + eval $cmd + echo $actName +} + +function getPackageName { + set -- $(getActivityName $1 | tr "[/]" "[ ]") + echo $1 +} + +function startActivityFromPackage { + if [ "$1" = home ]; then + doKeyevent HOME + echo 0 + return 0 + fi + vout $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN + $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN 2>&1 + echo 0 +} + +function startActivity { + if [ "$1" = home ]; then + doKeyevent HOME + echo 0 + return 0 + elif [ "$1" = chromeL ]; then + vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com + set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime) + else + vout $AM_START "$(getActivityName $1)" + set -- $($AM_START "$(getActivityName $1)" | grep ThisTime) + fi + echo $2 | tr "[\r]" "[\n]" +} + +function forceStartActivity { + if [ "$1" = chromeL ]; then + # force start doesn't work for chrome (hangs on startup) + startActivity $* + return 0 + else + vout $AM_FORCE_START "$(getActivityName $1)" + set -- $($AM_FORCE_START "$(getActivityName $1)" | grep ThisTime) + fi + echo $2 | tr "[\r]" "[\n]" +} + +function checkActivity { + # requires root + actName="$(getActivityName $1)" + $AM_LIST | grep $actName +} + +#function stopActivity { +# vout $AM_STOP $(getActivityName $1) +# $AM_STOP $(getActivityName $1) +#} + +function doSwipe { + vout ${ADB}input swipe $* + ${ADB}input swipe $* +} + +function doTap { + vout ${ADB}input tap $* + ${ADB}input tap $* +} + +function doKeyevent { + vout $INPUT keyevent $* + $INPUT keyevent $* +} + +function checkIsRunning { + p=$1 + shift + if ! $PS | grep $p | grep -qv grep; then + handleError $*: $p is not running + exit 1 + fi +} + +function checkStartTime { + vout checkStartTime $1 v $2 + if [ -z "$2" ]; then + echo false + return 2 + fi + if [ "$1" -gt "$2" ]; then + echo false + return 1 + fi + echo true + return 0 +} + +function handleError { + echo Error: $* + stopAndDumpInstramentation + if [ $stoponerror -gt 0 ]; then + exit 1 + fi +} + +user=root +if ${ADB}ls /data 2>/dev/null | grep -q "Permission denied"; then + user=shell +fi +vout User is $user + +if [ $generateActivities -gt 0 ]; then + if [ $isOnDevice -gt 0 ]; then + echo Error: cannot generate activity list when run on device + exit 1 + fi + echo Generating activities... + for app in $appList + do + startActivityFromPackage $app 2>&1 > /dev/null + act=$(${ADB}am stack list | grep $(getPackageName $app) | sed -e 's/
//' | head -1 | awk '{ print $2; }') + eval "${app}Activity=$act" + echo "ACTIVITY: $app --> $(getActivityName $app)" + done +fi + diff --git a/tests/workloads/feedly-chrome.sh b/tests/workloads/feedly-chrome.sh new file mode 100755 index 00000000..4c7002f9 --- /dev/null +++ b/tests/workloads/feedly-chrome.sh @@ -0,0 +1,111 @@ +# Script to automate the following sequence: +# - Open Feedly +# - Open an article +# - Scroll to bottome +# - Open the same article in Chrome +# - Scroll the article +# - Back to Feely (should still be in memory) +# - Home screen +# ---- repeat ---- +# +# Currently works on volantis only (verticle orientation) +# + +CMDDIR=$(dirname $0 2>/dev/null) +CMDDIR=${CMDDIR:=.} +. $CMDDIR/defs.sh + +case "$DEVICE" in +(volantis) + echo volantis... + feedlyArticle="500 700" + feedlyOptions="1480 100" + feedlyBrowserSelect="1350 650" + feedlyArticleSwipeUp="700 700 700 50 50" + feedlyArticleSwipeDown="700 200 700 700 50" + chromeSwipe="700 700 700 50 50" + ;; +(shamu|*) + echo shamu... + feedlyArticle="676 500" + feedlyOptions="1327 207" + feedlyBrowserSelect="1278 1191" + feedlyArticleSwipeUp="700 1847 700 400 50" + feedlyArticleSwipeDown="700 400 700 1847 50" + chromeSwipe="700 1847 700 400 50" + ;; +(hammerhead|*) + echo "Error: No feedly screen geometry information available for $DEVICE" + exit 1;; +esac + +feedlySwitchToTime=600 + +# start feedly, if not installed, error out +t=$(forceStartActivity feedly) +checkIsRunning feedly "initial start of feedly" +echo Feedly start time = ${t}ms + +# start chrome, if not installed, error out +t=$(forceStartActivity chrome) +checkIsRunning chrome "initial start of chrome" +echo Chrome start time = ${t}ms +sleep 1 + +feedlyStartTimes=0 + +cur=1 +while [ $cur -le $iterations ] +do + echo ======================================= + echo Iteration $cur of $iterations + echo ======================================= + startInstramentation + t=$(startActivity feedly) + if [ $(checkStartTime "$t" $feedlySwitchToTime) != true ]; then + handleError Feedly took too long to start: $t v $feedlySwitchToTime: $? + # for now, not fatal + # exit 1 + fi + sleep 2 + ((feedlyStartTimes=feedlyStartTimes+t)) + echo feedly started in ${t}ms + checkIsRunning chrome "switch back to feedly" + checkIsRunning googlequicksearchbox "switch back to feedly" + + # click on first article + doTap $feedlyArticle + sleep 2 + + # scroll through article + doSwipe $feedlyArticleSwipeUp + sleep 5 + checkIsRunning chrome "feedly swipe" + checkIsRunning googlequicksearchbox "feedly swipe" + + # scroll back to top + doSwipe $feedlyArticleSwipeDown + sleep 2 + + # switch to chrome + # 1. click on menu bar + doTap $feedlyOptions + sleep 1 + # 2. click on browser + doTap $feedlyBrowserSelect + sleep 10 + + checkIsRunning feedly "switch to chrome" + checkIsRunning googlequicksearchbox "switch to chrome" + + # Now we're back in chrome, swipe to bottom of article + doSwipe $chromeSwipe + sleep 2 + checkIsRunning feedly "swiped chrome" + stopInstramentation + ((cur=cur+1)) +done +((feedlyAve=feedlyStartTimes/iterations)) +echo Avg start times: feedly: ${feedlyAve}ms + +doKeyevent HOME diff --git a/tests/workloads/recentfling.sh b/tests/workloads/recentfling.sh new file mode 100755 index 00000000..68fdb2ff --- /dev/null +++ b/tests/workloads/recentfling.sh @@ -0,0 +1,132 @@ +# +# Script to start a set of apps, switch to recents and fling it back and forth. +# For each iteration, Total frames and janky frames are reported. +# +# Options are described below. +# +# Works for volantis, shamu, and hammerhead. Can be pushed and executed on +# the device. +# +iterations=10 +startapps=1 +capturesystrace=0 + +function processLocalOption { + ret=0 + case "$1" in + (-N) startapps=0;; + (-A) unset appList;; + (-L) appList=$2; shift; ret=1;; + (-T) capturesystrace=1;; + (*) + echo "$0: unrecognized option: $1" + echo; echo "Usage: $0 [options]" + echo "-A : use all known applications" + echo "-L applist : list of applications" + echo " default: $appList" + echo "-N : no app startups, just fling" + echo "-g : generate activity strings" + echo "-i iterations" + echo "-T : capture systrace on each iteration" + exit 1;; + esac + return $ret +} + +CMDDIR=$(dirname $0 2>/dev/null) +CMDDIR=${CMDDIR:=.} +. $CMDDIR/defs.sh + +case $DEVICE in +(shamu|hammerhead) + flingtime=300 + downCount=2 + upCount=6 + UP="70 400 70 100 $flingtime" + DOWN="70 100 70 400 $flingtime";; +(volantis) + flingtime=400 + downCount=5 + upCount=6 + UP="70 400 70 70 $flingtime" + DOWN="70 70 70 400 $flingtime";; +(*) + echo "Error: No display information available for $DEVICE" + exit 1;; +esac + +doKeyevent HOME +if [ $startapps -gt 0 ]; then + + # start a bunch of apps + for app in $appList + do + echo Starting $app ... + t=$(startActivity $app) + done +fi + +cur=1 + +set -- $(getJankyFrames) +totalFrames=$1 +jankyFrames=$2 +frameSum=0 +jankSum=0 + +if [ ${totalFrames:=0} -eq 0 ]; then +#echo Error: could not read frame info with \"dumpsys graphicsstats\" + echo Error: could not read frame info with \"dumpsys gfxinfo\" + exit 1 +fi + +function swipe { + count=0 + while [ $count -lt $2 ] + do + doSwipe $1 + ((count=count+1)) + done +} + +echo Fling recents... +doKeyevent APP_SWITCH + +while [ $cur -le $iterations ] +do + if [ $capturesystrace -gt 0 ]; then + ${ADB}atrace --async_start -z -c -b 16000 freq gfx view idle sched + fi + swipe "$DOWN" $downCount + sleep 1 + swipe "$UP" $upCount + sleep 1 + swipe "$DOWN" $downCount + sleep 1 + swipe "$UP" $upCount + sleep 1 + if [ $capturesystrace -gt 0 ]; then + ${ADB}atrace --async_dump -z -c -b 16000 freq gfx view idle sched > trace.${cur}.out + fi + + set -- $(getJankyFrames) + newTotalFrames=$1 + newJankyFrames=$2 + ((totalDiff=newTotalFrames-totalFrames)) + ((frameSum=frameSum+totalDiff)) + ((jankyDiff=newJankyFrames-jankyFrames)) + ((jankSum=jankSum+jankyDiff)) + if [ "$totalDiff" -eq 0 ]; then + echo Error: no frames detected. Is the display off? + exit 1 + fi + ((jankPct=jankyDiff*100/totalDiff)) + totalFrames=$newTotalFrames + jankyFrames=$newJankyFrames + + echo Frames: $totalDiff Janks: $jankyDiff \(${jankPct}%\) + ((cur=cur+1)) +done +doKeyevent HOME +((aveJankPct=jankSum*100/frameSum)) +echo AVE: Frames: $frameSum Janks: $jankSum \(${aveJankPct}%\) diff --git a/tests/workloads/systemapps.sh b/tests/workloads/systemapps.sh new file mode 100755 index 00000000..184c4ee4 --- /dev/null +++ b/tests/workloads/systemapps.sh @@ -0,0 +1,212 @@ +# Script to start a set of apps in order and then in each iteration +# switch the focus to each one. For each iteration, the time to start +# the app is reported as measured using atrace events and via am ThisTime. +# The output also reports if applications are restarted (eg, killed by +# LMK since previous iteration) or if there were any direct reclaim +# events. +# +# Variation: the "-T" option skips all of the atrace instramentation and +# attempts to start the apps as quickly as possible. +# +# Example 1: start all default apps. 2 iterations +# +# ./systemapps.sh -i 2 +# +# Example 2: just start chrome, feedly, and the home screen in a loop +# +# ./systemapps.sh -L "chrome feedly home" -i 5 +# +# Example 3: just start the default apps as quickly as possible +# +# ./systemapps.sh -T +# +# Other options are described below. +# +iterations=1 +tracecategories="gfx view am input memreclaim" +totaltimetest=0 +forcecoldstart=0 + +appList="gmail hangouts chrome youtube play home" + +function processLocalOption { + ret=0 + case "$1" in + (-A) unset appList;; + (-F) forcecoldstart=1;; + (-L) appList=$2; shift; ret=1;; + (-T) totaltimetest=1;; + (*) + echo "$0: unrecognized option: $1" + echo; echo "Usage: $0 [options]" + echo "-A : use all known applications" + echo "-F : force cold-start for all apps" + echo "-L applist : list of applications" + echo " default: $appList" + echo "-T : total time to start all apps" + echo "-g : generate activity strings" + echo "-i iterations" + echo "-n : keep trace files" + echo "-o output file" + echo "-s : stop on error" + echo "-t trace categories" + exit 1;; + esac + return $ret +} + +CMDDIR=$(dirname $0 2>/dev/null) +CMDDIR=${CMDDIR:=.} +. $CMDDIR/defs.sh + +tmpTraceOutBase=./tmptrace + +if [ $user != "root" -a $totaltimetest -eq 0 ]; then + handleError Must be root on device + exit 1 +fi +doKeyevent HOME + +function computeStats { + label=$1 + t=$2 + restart=$3 + reclaim=$4 + frames=$5 + janks=$6 + curMax=$(eval "echo \$${label}max") + curMax=${curMax:=0} + curMin=$(eval "echo \$${label}min") + curMin=${curMin:=100000} + curSum=$(eval "echo \$${label}sum") + curSum=${curSum:=0} + curRestart=$(eval "echo \$${label}restart") + curRestart=${curRestart:=0} + curReclaim=$(eval "echo \$${label}reclaim") + curReclaim=${curReclaim:=0} + curFrames=$(eval "echo \$${label}frames") + curFrames=${curFrames:=0} + curJanks=$(eval "echo \$${label}janks") + curJanks=${curJanks:=0} + if [ $curMax -lt $t ]; then + eval "${label}max=$t" + fi + if [ $curMin -gt $t ]; then + eval "${label}min=$t" + fi + ((curSum=curSum+t)) + eval "${label}sum=$curSum" + + ((curRestart=curRestart+${restart:=0})) + eval "${label}restart=$curRestart" + ((curReclaim=curReclaim+${reclaim:=0})) + eval "${label}reclaim=$curReclaim" + ((curFrames=curFrames+${frames:=0})) + eval "${label}frames=$curFrames" + ((curJanks=curJanks+${janks:=0})) + eval "${label}janks=$curJanks" +} +function getStats { + label=$1 + echo $(eval "echo \$${label}max") $(eval "echo \$${label}min") $(eval "echo \$${label}sum") \ + $(eval "echo \$${label}restart") $(eval "echo \$${label}reclaim") \ + $(eval "echo \$${label}frames") $(eval "echo \$${label}janks") +} + +cur=1 +totaltime=0 +startTimestamp=$(date +"%s %N") + +while [ $cur -le $iterations ] +do + if [ $iterations -gt 1 ]; then + echo ========================================= + echo Iteration $cur of $iterations + echo ========================================= + fi + if [ $iterations -gt 1 -o $cur -eq 1 ]; then + if [ $totaltimetest -eq 0 ]; then + printf "%-6s %7s(ms) %6s(ms) %s %s %s %s\n" App Time AmTime Restart DirReclaim JankyFrames + fi + fi + + appnum=-1 + for app in $appList + do + vout Starting $app... + ((appnum=appnum+1)) + loopTimestamp=$(date +"%s %N") + if [ $totaltimetest -gt 0 ]; then + # no instramentation, just cycle through the apps + if [ $appnum -eq 0 ]; then + printf "%-8s %5s(ms) %3s(ms)\n" App Start Iter + fi + if [ $forcecoldstart -eq 0 ]; then + t=$(startActivity $app) + else + t=$(forceStartActivity $app) + fi + loopEndTimestamp=$(date +"%s %N") + diffTime=$(computeTimeDiff $loopTimestamp $loopEndTimestamp) + # Note: "%d" doesn't work right if run on device + printf "%-10s %5.0f %5.0f\n" $app $t $diffTime + ((totaltime=totaltime+t)) + continue + fi + tmpTraceOut="$tmpTraceOutBase-$app.out" + >$tmpTraceOut + startInstramentation + resetJankyFrames $(getPackageName $app) + t=$(startActivity $app) + # let app finish drawing before checking janks + sleep 3 + set -- $(getJankyFrames $(getPackageName $app)) + frames=$1 + janks=$2 + ((jankPct=100*janks/frames)) + stopAndDumpInstramentation $tmpTraceOut + actName=$(getActivityName $app) + stime=$(getStartTime $actName $tmpTraceOut) + relaunch=$? + etime=$(getEndTime $actName $tmpTraceOut) + ((tdiff=$etime-$stime)) + if [ $etime -eq 0 -o $stime -eq 0 ]; then + handleError $app : could not compute start time stime=$stime etime=$etime + # use AmTime so statistics make sense + tdiff=$t + fi + checkForDirectReclaim $actName $tmpTraceOut + directReclaim=$? + + printf "%-12s %5d %5d %5d %5d %5d(%d%%)\n" "$app" "$tdiff" "$t" "$relaunch" "$directReclaim" "$janks" "$jankPct" + computeStats "$app" "$tdiff" "$relaunch" "$directReclaim" "$frames" "$janks" + + if [ $savetmpfiles -eq 0 ]; then + rm -f $tmpTraceOut + fi + done + ((cur=cur+1)) +done +endTimestamp=$(date +"%s %N") +diffTime=$(computeTimeDiff $startTimestamp $endTimestamp) +if [ $totaltimetest -gt 0 ]; then + printf "%-10s %5.0f %5.0f\n" TOTAL $totaltime $diffTime +fi + +if [ $iterations -gt 1 -a $totaltimetest -eq 0 ]; then + echo + echo ========================================= + printf "Stats after $iterations iterations:\n" + echo ========================================= + printf "%-6s %7s(ms) %6s(ms) %6s(ms) %s %s %s %s\n" App Max Ave Min Restart DirReclaim JankyFrames + for app in $appList + do + set -- $(getStats $app) + sum=$3 + ((ave=sum/iterations)) + frames=$6 + janks=$7 + ((jankPct=100*janks/frames)) + printf "%-12s %5d %5d %5d %5d %5d %5d(%d%%)\n" $app $1 $ave $2 $4 $5 $janks $jankPct + done +fi |