You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
522 lines
15 KiB
522 lines
15 KiB
#!/bin/sh -u
|
|
|
|
parseoptions() {
|
|
trace_reads=false
|
|
trace_writes=false
|
|
trace_writepages=false
|
|
pid_view=false
|
|
|
|
while [ $# -ge 1 ]
|
|
do
|
|
case $1 in
|
|
-r)
|
|
trace_reads=true
|
|
;;
|
|
-w)
|
|
trace_writes=true
|
|
;;
|
|
-p)
|
|
trace_writepages=true
|
|
;;
|
|
-v)
|
|
pid_view=true
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
usage() {
|
|
echo "Usage: $0 [-r|-w|-p|-v]"
|
|
exit 1
|
|
}
|
|
|
|
getmodel() {
|
|
model=`adb shell getprop ro.product.name`
|
|
# Releases are inconsistent with various trailing characters, remove them all
|
|
model=`echo $model | sed 's/[ \t\r\n]*$//' `
|
|
echo Found $model Device
|
|
|
|
case $model in
|
|
aosp_gobo | gobo | gobo_512)
|
|
get_go_devnames
|
|
;;
|
|
marlin | sailfish | walleye | taimen | blueline | crosshatch)
|
|
get_marlin_sailfish_devnames
|
|
;;
|
|
angler)
|
|
get_angler_devnames
|
|
;;
|
|
bullhead)
|
|
get_bullhead_devnames
|
|
;;
|
|
volantis | volantisg)
|
|
get_volantis_devnames
|
|
;;
|
|
*)
|
|
echo Unknown Device $model -- trying Pixel config
|
|
get_marlin_sailfish_devnames
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_go_devnames () {
|
|
# Hardcoding all of the mmcblk0 device for now
|
|
block_device=mmcblk0
|
|
bdev_set=true
|
|
}
|
|
|
|
get_volantis_devnames() {
|
|
bdev_set=true
|
|
block_device=mmcblk0
|
|
}
|
|
|
|
get_bullhead_devnames() {
|
|
bdev_set=true
|
|
block_device=mmcblk0
|
|
}
|
|
|
|
get_marlin_sailfish_devnames() {
|
|
bdev_set=true
|
|
block_device=sda
|
|
}
|
|
|
|
get_angler_devnames () {
|
|
# Get the underlying bdev from the "by-name" mapping
|
|
block_device=`adb shell 'find /dev/block/platform -name by-name | xargs ls -l' | grep system | awk '{ print $10 }' `
|
|
# extract the last component of the absolute device pathname we got above
|
|
block_device=`echo $block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' | sed 's/p.*//g' `
|
|
bdev_set=true
|
|
}
|
|
|
|
disk_stats_before() {
|
|
if [ $bdev_set == true ]; then
|
|
DISKSTATS=`adb shell 'cat /proc/diskstats' | fgrep -w $block_device `
|
|
# Get BEFORE read stats for bdev
|
|
BEFORE_RD_IOS=`echo $DISKSTATS | awk '{ print $4 }' `
|
|
BEFORE_RD_SECTORS=`echo $DISKSTATS | awk '{ print $6 }' `
|
|
# Get BEFORE write stats for bdev
|
|
BEFORE_WR_IOS=`echo $DISKSTATS | awk '{ print $8 }' `
|
|
BEFORE_WR_SECTORS=`echo $DISKSTATS | awk '{ print $10 }' `
|
|
fi
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
adb shell 'mount -o remount,background_gc=off /data'
|
|
F2FS_GC_SEGMENTS_BEFORE=`adb shell 'cat /sys/kernel/debug/f2fs/status' | grep segments | egrep 'data|node' | awk '{ segments += $5 } END { print segments }' `
|
|
fi
|
|
}
|
|
|
|
disk_stats_after() {
|
|
if [ $bdev_set == true ]; then
|
|
DISKSTATS=`adb shell 'cat /proc/diskstats' | fgrep -w $block_device `
|
|
# Get AFTER read stats for bdev
|
|
AFTER_RD_IOS=`echo $DISKSTATS | awk '{ print $4 }' `
|
|
AFTER_RD_SECTORS=`echo $DISKSTATS | awk '{ print $6 }' `
|
|
# Get BEFORE write stats for bdev
|
|
AFTER_WR_IOS=`echo $DISKSTATS | awk '{ print $8 }' `
|
|
AFTER_WR_SECTORS=`echo $DISKSTATS | awk '{ print $10 }' `
|
|
fi
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
F2FS_GC_SEGMENTS_AFTER=`adb shell 'cat /sys/kernel/debug/f2fs/status' | grep segments | egrep 'data|node' | awk '{ segments += $5 } END { print segments }' `
|
|
adb shell 'mount -o remount,background_gc=on /data'
|
|
fi
|
|
}
|
|
|
|
disk_stats_delta_rd() {
|
|
file_data_KB=$1
|
|
if [ $bdev_set == true ]; then
|
|
# Sectors to KB
|
|
READ_KB=`expr $AFTER_RD_SECTORS - $BEFORE_RD_SECTORS`
|
|
READ_KB=`expr $READ_KB / 2`
|
|
echo "Total (ALL) Read KB $block_device = "$READ_KB
|
|
BLOCK_MINUS_FILE=`expr $READ_KB - $file_data_KB`
|
|
echo "READ DELTA: Total Blockdev Reads KB - Total File Data Reads KB = "$BLOCK_MINUS_FILE KB
|
|
echo "Total (ALL) Read IOs $block_device = "`expr $AFTER_RD_IOS - $BEFORE_RD_IOS`
|
|
fi
|
|
}
|
|
|
|
disk_stats_delta_wr() {
|
|
file_data_KB=$1
|
|
if [ $bdev_set == true ]; then
|
|
# Sectors to KB
|
|
WRITE_KB=`expr $AFTER_WR_SECTORS - $BEFORE_WR_SECTORS`
|
|
WRITE_KB=`expr $WRITE_KB / 2`
|
|
BLOCK_MINUS_FILE=`expr $WRITE_KB - $file_data_KB`
|
|
echo "WRITE DELTA: Total Blockdev Writes KB - Total File Data Writes KB = "$BLOCK_MINUS_FILE KB
|
|
echo "Total (ALL) Write IOs $block_device = "`expr $AFTER_WR_IOS - $BEFORE_WR_IOS`
|
|
fi
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
F2FS_GC_SEGMENTS_DELTA=`expr $F2FS_GC_SEGMENTS_AFTER - $F2FS_GC_SEGMENTS_BEFORE`
|
|
F2FS_GC_KB_DELTA=`expr $F2FS_GC_SEGMENTS_DELTA \\* 2048`
|
|
fi
|
|
}
|
|
|
|
# For good measure clean up traces and reenable traces
|
|
clean_up_tracepoints() {
|
|
# This is a good point to check if the Android FS tracepoints are enabled in the
|
|
# kernel or not
|
|
tracepoint_exists=`adb shell 'if [ -d /sys/kernel/debug/tracing/events/android_fs ]; then echo 0; else echo 1; fi' `
|
|
if [ $tracepoint_exists == 1 ]; then
|
|
echo "Android FS tracepoints not enabled in kernel. Exiting..."
|
|
exit 1
|
|
fi
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/tracing_on'
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/trace'
|
|
if [ $trace_reads == true ]; then
|
|
adb shell 'echo 1 > /sys/kernel/debug/tracing/events/android_fs/android_fs_dataread_start/enable'
|
|
fi
|
|
if [ $trace_writes == true ]; then
|
|
adb shell 'echo 1 > /sys/kernel/debug/tracing/events/android_fs/android_fs_datawrite_start/enable'
|
|
fi
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
if [ $trace_writepages == true ]; then
|
|
adb shell 'echo 1 > /sys/kernel/debug/tracing/events/android_fs/android_fs_writepages/enable'
|
|
fi
|
|
fi
|
|
adb shell 'echo 1 > /sys/kernel/debug/tracing/tracing_on'
|
|
}
|
|
|
|
# stream trace out of trace_pipe
|
|
# Start this in the background ('&')
|
|
streamtrace_start() {
|
|
adb shell cat /sys/kernel/debug/tracing/trace_pipe > trace_saved
|
|
}
|
|
|
|
# When signal is received, the trace_pipe reader will get killed
|
|
# Call this (just to make sure anyway)
|
|
streamtrace_end() {
|
|
ps_line=`ps -ef | grep trace_pipe | grep adb `
|
|
if [ $? == 0 ]; then
|
|
echo Killing `echo $ps_line | awk '{s = ""; for (i=8; i <= NF ; i++) s = s $i " "; print s}' `
|
|
kill `echo $ps_line | awk '{print $2}' `
|
|
fi
|
|
}
|
|
|
|
copyout_trace() {
|
|
streamtrace_end
|
|
if [ $trace_reads == true ]; then
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/events/android_fs/android_fs_dataread_start/enable'
|
|
fi
|
|
if [ $trace_writes == true ]; then
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/events/android_fs/android_fs_datawrite_start/enable'
|
|
fi
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
if [ $trace_writepages == true ]; then
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/events/android_fs/android_fs_writepages/enable'
|
|
fi
|
|
fi
|
|
adb shell 'echo 0 > /sys/kernel/debug/tracing/tracing_on'
|
|
}
|
|
|
|
prep_tracefile_common() {
|
|
cp trace_saved $infile
|
|
# Strip away all the extraneous stuff first
|
|
fgrep $1 $infile | sed 's/^.* \[.*\] //' | sed s/://g | sed s/,//g > foo
|
|
mv foo $infile
|
|
}
|
|
|
|
prep_tracefile_rd() {
|
|
prep_tracefile_common android_fs_dataread
|
|
# Strip away unnecessary stuff so we can compute latencies easily
|
|
fgrep android_fs_dataread_start $infile > foo0
|
|
# Throw away everything upto and including android_fs_dataread:
|
|
cat foo0 | sed -n -e 's/^.*android_fs_dataread_start //p' > foo1
|
|
mv foo1 $infile
|
|
# At this stage, $infile should the following format :
|
|
# entry_name <filename> offset <offset> bytes <bytes> cmdline <cmdline> pid <pid> i_size <i_size> ino <ino>
|
|
rm foo0
|
|
}
|
|
|
|
prep_tracefile_writepages() {
|
|
prep_tracefile_common android_fs_writepages
|
|
# Throw away everything up to and including android_fs_writepages_start:
|
|
cat $infile | sed -n -e 's/^.*android_fs_writepages //p' > foo1
|
|
mv foo1 $infile
|
|
# At this stage, $infile should the following format :
|
|
# entry_name <filename> bytes <bytes> ino <ino>
|
|
}
|
|
|
|
# Latencies not supported for Writes. 'Write End' is just when the data has been
|
|
# written back to page cache.
|
|
prep_tracefile_wr() {
|
|
prep_tracefile_common android_fs_datawrite
|
|
fgrep android_fs_datawrite_start $infile > foo0
|
|
# Throw away everything upto and including android_fs_datawrite:
|
|
cat foo0 | sed -n -e 's/^.*android_fs_datawrite_start //p' > foo1
|
|
mv foo1 $infile
|
|
# At this stage, $infile should the following format :
|
|
# entry_name <filename> offset <offset> bytes <bytes> cmdline <cmdline> pid <pid> i_size <i_size> ino <ino>
|
|
rm foo0
|
|
}
|
|
|
|
get_unique_files_rw() {
|
|
# Sort first by filename, then by pid
|
|
cat $infile | sed s/,//g | sort -d -k2,2 -k8,8 > foo1
|
|
mv foo1 $infile
|
|
# $infile now contains lines sorted by <filename, pid>
|
|
# How many unique files are there ?
|
|
cat $infile | awk '{ print $2 }' > foo1
|
|
cat foo1 | uniq > uniq_files
|
|
rm foo1
|
|
}
|
|
|
|
get_unique_files_writepages() {
|
|
cat $infile | sed s/,//g | sort -d -k2,2 > foo1
|
|
# $infile now contains lines sorted by <filename>
|
|
mv foo1 $infile
|
|
# How many unique files are there ?
|
|
cat $infile | awk '{ print $2 }' > foo1
|
|
cat foo1 | uniq > uniq_files
|
|
rm foo1
|
|
}
|
|
|
|
get_unique_pids_byfile() {
|
|
# How many unique pids are there reading this file ?
|
|
cat $1 | awk '{ print $8 }' > foo1
|
|
cat foo1 | uniq > uniq_pids_byfile
|
|
rm foo1
|
|
}
|
|
|
|
get_unique_pids() {
|
|
# Sort first by pid, then by filename
|
|
cat $infile | sed s/,//g | sort -d -k8,8 -k2,2 > foo1
|
|
mv foo1 $infile
|
|
# $infile now contains lines sorted by <pid, filename>
|
|
# How many unique pids are there ?
|
|
cat $infile | awk '{ print $8 }' > foo1
|
|
cat foo1 | uniq > uniq_pids
|
|
rm foo1
|
|
}
|
|
|
|
get_unique_files_bypid() {
|
|
# How many unique files are there read by this pid ?
|
|
cat $1 | awk '{ print $2 }' > foo1
|
|
cat foo1 | uniq > uniq_files_bypid
|
|
rm foo1
|
|
}
|
|
|
|
catch_sigint()
|
|
{
|
|
echo "signal INT received, killing streaming trace capture"
|
|
streamtrace_end
|
|
}
|
|
|
|
|
|
prep_to_do_something() {
|
|
# adb shell "am force-stop com.android.chrome"
|
|
# adb shell "am force-stop com.google.android.gm"
|
|
adb shell 'echo 3 > /proc/sys/vm/drop_caches'
|
|
sleep 1
|
|
}
|
|
|
|
do_something() {
|
|
# Arrange things so that the first SIGINT will kill the
|
|
# child process (sleep), but will return to the parent.
|
|
trap 'catch_sigint' INT
|
|
echo "OK to kill sleep when test is done"
|
|
sleep 30d
|
|
# adb shell "am start -W -n com.android.chrome/com.google.android.apps.chrome.Main"
|
|
# adb shell "am start -W -n com.google.android.gm/.ConversationListActivityGmail"
|
|
}
|
|
|
|
# Get the aggregate list of files read/written. For each file, break up the IOs by pid
|
|
process_files_rw() {
|
|
read_write=$1
|
|
get_unique_files_rw
|
|
# Loop over each file that was involved in IO
|
|
# Find all the pids doing IO on that file
|
|
# Aggregate the IO done by each pid on that file and dump it out
|
|
grand_total_KB=0
|
|
cp $infile tempfile
|
|
for i in `cat uniq_files`
|
|
do
|
|
# Get just the tracepoints for this file
|
|
fgrep -w "$i" tempfile > subtrace
|
|
if [ -s subtrace ]; then
|
|
echo "File: $i"
|
|
total_file_KB=0
|
|
# Remove the tracepoints we just picked up
|
|
fgrep -v -w "$i" tempfile > foo
|
|
mv foo tempfile
|
|
# Get all the pids doing IO on this file
|
|
get_unique_pids_byfile subtrace
|
|
for j in `cat uniq_pids_byfile`
|
|
do
|
|
echo -n " $j $read_write: "
|
|
pid_KB=`fgrep -w "$j" subtrace | awk '{ bytes += $6 } END { print bytes }' `
|
|
pid_KB=`expr $pid_KB / 1024`
|
|
echo "$pid_KB KB"
|
|
total_file_KB=`expr $total_file_KB + $pid_KB`
|
|
done
|
|
i_size=`tail -n1 subtrace | awk '{ if ($12 > 1024) printf "%d KB", ($12/1024); else printf "%d bytes", $12; }' `
|
|
echo " Total $read_write: $total_file_KB KB i_size: $i_size"
|
|
grand_total_KB=`expr $grand_total_KB + $total_file_KB`
|
|
fi
|
|
done
|
|
echo "Grand Total File DATA KB $read_write $grand_total_KB"
|
|
rm tempfile
|
|
}
|
|
|
|
process_files_writepages() {
|
|
get_unique_files_writepages
|
|
# Loop over each file that was involved in IO
|
|
# Aggregate the IO done on that file and dump it out
|
|
grand_total_KB=0
|
|
cp $infile tempfile
|
|
for i in `cat uniq_files`
|
|
do
|
|
# Get just the tracepoints for this file
|
|
fgrep -w "$i" tempfile > subtrace
|
|
if [ -s subtrace ]; then
|
|
fgrep -v -w "$i" tempfile > foo
|
|
mv foo tempfile
|
|
total_file_KB=`cat subtrace | awk '{ bytes += $4 } END { print bytes }' `
|
|
total_file_KB=`expr $total_file_KB / 1024`
|
|
if [ $total_file_KB -gt 0 ]; then
|
|
echo "File: $i Total $read_write: $total_file_KB KB"
|
|
grand_total_KB=`expr $grand_total_KB + $total_file_KB`
|
|
fi
|
|
fi
|
|
done
|
|
echo "Grand Total File DATA KB Writepages $grand_total_KB"
|
|
rm tempfile
|
|
}
|
|
|
|
# Get the aggregate list of pids. For each pid, break up the IOs by file
|
|
process_pids() {
|
|
read_write=$1
|
|
get_unique_pids
|
|
list_of_pids=`cat uniq_pids`
|
|
# $list_of_pids is a list of all the pids involved in IO
|
|
#
|
|
# Loop over each pid that was involved in IO
|
|
# Find all the files the pid was doing IO on
|
|
# Aggregate the IO done by the pid for each file and dump it out
|
|
#
|
|
grand_total_KB=0
|
|
for i in $list_of_pids
|
|
do
|
|
echo "PID: $i"
|
|
total_pid_KB=0
|
|
# Get just the tracepoints for this pid
|
|
fgrep -w "$i" $infile > subtrace
|
|
# Get all the pids doing IO on this file
|
|
get_unique_files_bypid subtrace
|
|
list_of_files=`cat uniq_files_bypid`
|
|
# $list_of_files is a list of all the files IO'ed by this pid
|
|
for j in $list_of_files
|
|
do
|
|
i_size=`fgrep -w "$j" subtrace | tail -n1 | awk '{ if ($12 > 1024) printf "%d KB", ($12/1024); else printf "%d bytes", $12; }' `
|
|
file_KB=`fgrep -w "$j" subtrace | awk '{ bytes += $6 } END { print bytes }' `
|
|
file_KB=`expr $file_KB / 1024`
|
|
echo " $j $read_write: $file_KB KB i_size: $i_size"
|
|
total_pid_KB=`expr $total_pid_KB + $file_KB`
|
|
done
|
|
echo " Total $read_write: $total_pid_KB KB"
|
|
grand_total_KB=`expr $grand_total_KB + $total_pid_KB`
|
|
done
|
|
echo "Grand Total File DATA KB $read_write $grand_total_KB"
|
|
}
|
|
|
|
# main() starts here :
|
|
|
|
if [ $# -lt 1 ]; then
|
|
usage
|
|
fi
|
|
|
|
bdev_set=false
|
|
infile=tracefile.$$
|
|
|
|
parseoptions $@
|
|
adb root && sleep 2
|
|
getmodel
|
|
|
|
found_f2fs=`adb shell 'mount | grep f2fs > /dev/null; echo $?' `
|
|
|
|
if [ $found_f2fs == 0 ]; then
|
|
f2fs_fs=1
|
|
else
|
|
f2fs_fs=0
|
|
fi
|
|
|
|
if [ $f2fs_fs == 0 ] && [ $trace_writepages == true ]; then
|
|
echo "Writepages is only supported with f2fs, please use -r, -w"
|
|
exit 1
|
|
fi
|
|
|
|
prep_to_do_something
|
|
|
|
clean_up_tracepoints
|
|
disk_stats_before
|
|
# Start streaming the trace into the tracefile
|
|
streamtrace_start &
|
|
|
|
do_something
|
|
|
|
streamtrace_end
|
|
disk_stats_after
|
|
|
|
copyout_trace
|
|
|
|
if [ $trace_reads == true ]; then
|
|
echo
|
|
echo "READS :"
|
|
echo "_______"
|
|
echo
|
|
prep_tracefile_rd
|
|
# Get file specific stats - for each file, how many pids read that file ?
|
|
echo "FILE VIEW:"
|
|
process_files_rw Reads
|
|
if [ $pid_view == true ]; then
|
|
# Get pid specific stats - for each pid, what files do they do IO on ?
|
|
echo "PID VIEW:"
|
|
process_pids Reads
|
|
fi
|
|
disk_stats_delta_rd $grand_total_KB
|
|
|
|
debug_FileKB_rd=`cat $infile | awk '{ bytes += $6 } END { printf "%d", bytes/1024 }' `
|
|
echo Debug Grand Total KB READ $debug_FileKB_rd
|
|
fi
|
|
|
|
if [ $trace_writes == true ]; then
|
|
echo
|
|
echo "Writes :"
|
|
echo "_______"
|
|
echo
|
|
prep_tracefile_wr
|
|
# Get file specific stats - for each file, how many pids read that file ?
|
|
|
|
echo "FILE VIEW:"
|
|
process_files_rw Writes
|
|
if [ $pid_view == true ]; then
|
|
# Get pid specific stats - for each pid, what files do they do IO on ?
|
|
echo "PID VIEW:"
|
|
process_pids Writes
|
|
fi
|
|
disk_stats_delta_wr $grand_total_KB
|
|
|
|
if [ $f2fs_fs == 1 ] ; then
|
|
echo f2fs GC_KB delta = $F2FS_GC_KB_DELTA
|
|
fi
|
|
fi
|
|
|
|
if [ $f2fs_fs == 1 ] && [ $trace_writepages == true ] ; then
|
|
echo
|
|
echo "Writepages :"
|
|
echo "__________"
|
|
echo
|
|
prep_tracefile_writepages
|
|
# Get file specific stats - for each file, how much did we writepage ?
|
|
|
|
echo "FILE VIEW:"
|
|
process_files_writepages
|
|
|
|
disk_stats_delta_wr $grand_total_KB
|
|
|
|
echo f2fs GC_KB delta = $F2FS_GC_KB_DELTA
|
|
fi
|
|
|
|
rm -rf tracefile* uniq_* subtrace trace_saved
|