What is it ?
----------
ioblame is a IO profiler. It gives a detailed listing of the list of
files that running pids are doing IO to (with the aggregate amount of
read/write to each file). The goal is that using this tool, app
developers can identify IO heavy paths, and tune them, then
iteratively run this tool again to measure improvements/IO reduction.

ioblame is implemented as a collection of kernel filesystem
tracepoints, and a script.

What does the output from ioblame look like ?
-------------------------------------------
ioblame gives 2 different views.

File view is the default.

1) File view : For each file, it gives a list of pids that are doing
IO on that file (it also gives the amount of IO each pid does and
the aggregate amount of IO done to the file by all pids).

File: /app/Chrome/Chrome.apk
            Chrome_ChildIOT Reads: 96 KB
            Chrome_DBThread Reads: 652 KB
            Chrome_FileUser Reads: 72 KB
            Chrome_InProcGp Reads: 732 KB
            Chrome_IOThread Reads: 1396 KB
            Compositor Reads: 652 KB
            CookieMonsterBa Reads: 284 KB
            CrRendererMain Reads: 17012 KB
            dboxed_process0 Reads: 512 KB
            JavaBridge Reads: 128 KB
            ogle.android.gm Reads: 14996 KB
            WorkerPool/8556 Reads: 408 KB
            Total Reads: 36940 KB i_size: 71354 KB
File: /app/Gmail2Light/Gmail2Light.apk
            AsyncTask_#2 Reads: 24 KB
            Chrome_IOThread Reads: 68 KB
            ogle.android.gm Reads: 1440 KB
            Thread-6 Reads: 8 KB
            Total Reads: 1540 KB i_size: 9736 KB

And ditto for writes.

To enable PID view, use -v

PID: CrRendererMain
            /app/Chrome/Chrome.apk Reads: 17012 KB i_size: 71354 KB
            /etc/fonts.xml Reads: 24 KB i_size: 22 KB
            /fonts/CarroisGothicSC-Regular.ttf Reads: 40 KB i_size: 39 KB
            /fonts/ComingSoon.ttf Reads: 60 KB i_size: 57 KB
            /fonts/CutiveMono.ttf Reads: 68 KB i_size: 67 KB
            /fonts/DancingScript-Bold.ttf Reads: 116 KB i_size: 112 KB
            /fonts/DancingScript-Regular.ttf Reads: 116 KB i_size: 113 KB
            /fonts/DroidSansMono.ttf Reads: 108 KB i_size: 105 KB
            /fonts/NotoColorEmoji.ttf Reads: 204 KB i_size: 7108 KB
            /fonts/NotoNaskhArabic-Bold.ttf Reads: 116 KB i_size: 113 KB
,,,
	    /fonts/NotoSerif-BoldItalic.ttf Reads: 248 KB i_size: 256 KB
            /fonts/NotoSerif-Bold.ttf Reads: 244 KB i_size: 242 KB
            /fonts/NotoSerif-Italic.ttf Reads: 244 KB i_size: 243 KB
            /fonts/NotoSerif-Regular.ttf Reads: 244 KB i_size: 240 KB
            /fonts/Roboto-BlackItalic.ttf Reads: 256 KB i_size: 322 KB
            /fonts/Roboto-Black.ttf Reads: 256 KB i_size: 299 KB
            /fonts/Roboto-BoldItalic.ttf Reads: 256 KB i_size: 324 KB
            /fonts/RobotoCondensed-BoldItalic.ttf Reads: 256 KB i_size: 322 KB
            /fonts/RobotoCondensed-Bold.ttf Reads: 256 KB i_size: 296 KB
            /fonts/RobotoCondensed-Italic.ttf Reads: 256 KB i_size: 321 KB
            /fonts/RobotoCondensed-LightItalic.ttf Reads: 256 KB i_size: 324 KB
            /fonts/RobotoCondensed-Light.ttf Reads: 256 KB i_size: 295 KB
            /fonts/RobotoCondensed-MediumItalic.ttf Reads: 256 KB i_size: 322 KB
            /fonts/RobotoCondensed-Medium.ttf Reads: 256 KB i_size: 296 KB
            /fonts/Roboto-LightItalic.ttf Reads: 256 KB i_size: 324 KB
            /fonts/Roboto-MediumItalic.ttf Reads: 256 KB i_size: 323 KB
            /fonts/Roboto-Regular.ttf Reads: 88 KB i_size: 298 KB
            /fonts/Roboto-ThinItalic.ttf Reads: 256 KB i_size: 321 KB
            /fonts/Roboto-Thin.ttf Reads: 256 KB i_size: 300 KB
            /lib/libft2.so Reads: 56 KB i_size: 479 KB
            /lib/libicuuc.so Reads: 88 KB i_size: 1182 KB
            Total Reads: 32760 KB

And ditto for writes.

For the -p, writepages option, ioblame does not (and cannot) give you
the app/pid that did the original write (since the write most likely
happens from a flush thread or VM reclaim). In this mode, we only get
the pathname of the file and the amount of data written out.

Finally, it reports the total amount of file data IO done by pids and
the total IO done to the block device. So we can look at IO overheads
(eg block level prefetching, filesystem metadata overhead etc).

For detailed examples, look at ioblame-gmail-launch.example and
ioblame-gmail-run.example.

How do I run ioblame ?
--------------------
ioblame -r	[ I am only interested in reads ]
ioblame -w	[ I am only interested in writes ]
ioblame -p	[ I am only interested in writepage(s) - mmap'ed writes ]
ioblame -r -w -p [ I am only interested in reads, writes and writepages ]
and finally, -v adds the PID view

1) The most common way of running ioblame is to start ioblame, then go
off and launch the app(s) of interest, do interesting stuff with the
app(s), and when finished with the app, hit ^C ONCE on
ioblame. Hitting ^C once will cause ioblame to catch the signal, break
out of the sleep, terminate its tracing, and process the ftraces and
dump out IO stats for the app.

example :

srmohan0.mtv.corp.google.com> sh ioblame.sh  -r -w -p
Found aosp_gobo Device
OK to kill sleep when test is done
^Csignal INT received, killing streaming trace capture

(at this point, run your apps, when done type ^C ONCE) and output will
appear on stdout.

2) Sometimes, we want to do IO profiling in a different way (instead of
running something and then hitting ^C on ioblame). For instance, we
might want to do IO profiling related to the launch of an App. This
requires you to modify the script slightly, as described in the next
paragraph.

If you want to do IO profiling related to App launch, you need to modify
2 functions - prep_to_do_something and do_something. Again examples of
changes to these functions clarifies things better :

prep_to_do_something() {
    adb shell "am force-stop com.google.android.gm" # This line I added for example
    	      	  	     			    # stops the running app (gmail)
    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 1d
     # For the purpose of this example, I commented out the above 3 lines that
     # make ioblame sleep forever after catching the SIGINT and instead it launches
     # gmail, waiting for launch to complete. When launch completes, ioblame will
     # stop tracing, and process the traces
    adb shell "am start -W -n com.google.android.gm/.ConversationListActivityGmail"
}

Limitations :
-----------
The ioblame kernel tracepoints currently only cover the getpage(s)
path (so all filesystem reads) and filesystem write() syscalls. There
are no tracepoints in the putpage(s) paths. This is because when
putpage(s) is called, we most often cannot tell which thread/pid has
dirtied the page that is being written out, because the majority of
putpage(s) happen from the flush threads or from the pageout
threads. The upshot of this is the mmap'ed writes are not reported by
ioblame. In practice, while mmap'ed reads are very common, mmap'ed
writes are infrequent.

Kernel Patches Required :
-----------------------
ioblame needs the kernel to be patched with these 3 kernel patches.
Without these patches, ioblame won't work at all.

commit ae2f6765db98e2fcb99082e336dd8b24e7644620
Author: Mohan Srinivasan <srmohan@google.com>
Date:   Fri Mar 10 16:08:30 2017 -0800

    ANDROID: Replace spaces by '_' for some android filesystem tracepoints.

    Andoid files frequently have spaces in them, as do cmdline strings.
    Replace these spaces with '_', so tools that parse these tracepoints
    don't get terribly confused.

    Change-Id: I1cbbedf5c803aa6a58d9b8b7836e9125683c49d1
    Signed-off-by: Mohan Srinivasan <srmohan@google.com>
    (cherry picked from commit 5035d5f0933758dd515327d038e5bef7e40dbaa7)

commit a2a04ea83d2960867324fa059ba1eedc2fc7784e (HEAD -> android-4.4)
Author: Mohan Srinivasan <srmohan@google.com>
Date:   Fri Feb 3 15:48:03 2017 -0800

    ANDROID: Refactor fs readpage/write tracepoints.

    Refactor the fs readpage/write tracepoints to move the
    inode->path lookup outside the tracepoint code, and pass a pointer
    to the path into the tracepoint code instead. This is necessary
    because the tracepoint code runs non-preemptible. Thanks to
    Trilok Soni for catching this in 4.4.

    Change-Id: I7486c5947918d155a30c61d6b9cd5027cf8fbe15
    Signed-off-by: Mohan Srinivasan <srmohan@google.com>

commit 32cbbe59538d2dd0b77822cc27ce32ca487c467d
Author: Mohan Srinivasan <srmohan@google.com>
Date:   Mon Sep 19 17:33:50 2016 -0700

    ANDROID: fs: FS tracepoints to track IO.

    Adds tracepoints in ext4/f2fs/mpage to track readpages/buffered
    write()s. This allows us to track files that are being read/written
    to PIDs.

    Change-Id: I26bd36f933108927d6903da04d8cb42fd9c3ef3d
    Signed-off-by: Mohan Srinivasan <srmohan@google.com>

The -w (writepages) option requires this additional patch and
currently only with f2fs.

commit c60bc59c6af4fbdeaf7bbeaebee6b55d9e488324 (HEAD ->
android-mtk-gobo-3.18)
Author: Mohan Srinivasan <srmohan@google.com>
Date:   Fri Sep 8 13:53:01 2017 -0700

    Tracepoints in f2fs data writepage(s).

    Tracepoints f2fs writepage(s). This is experimental (for now).
    Allowing ioblame to track <pathname, amount of data written>
    for files.

    Signed-off-by: Mohan Srinivasan <srmohan@google.com>
    Change-Id: I4c76c6f442e0a2c5872225f8113935f9f368cc64
