Skip to content

Commit

Permalink
Adding ioblame. A tool for App IO profiling.
Browse files Browse the repository at this point in the history
ioblame is a tool for profiling App IO workloads. See the README for
more details on ioblame and how to use it.

Change-Id: Id56f827c2a8b744e24e3b21b535a59bd458f3de4
Signed-off-by: Mohan Srinivasan <[email protected]>
  • Loading branch information
Mohan Srinivasan authored and gitkaiser committed Jul 11, 2017
1 parent c952f47 commit a69f1ec
Show file tree
Hide file tree
Showing 5 changed files with 2,550 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ioblame/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_PREBUILT_EXECUTABLES := ioblame.sh
include $(BUILD_HOST_PREBUILT)
200 changes: 200 additions & 0 deletions ioblame/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
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.

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.

2) PID view : For each pid actively doing IO, it dumps out the list of
files that the pid does IO to.

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.

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 -r -w [ I am only interested in reads and writes ]

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
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 <[email protected]>
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 <[email protected]>
(cherry picked from commit 5035d5f0933758dd515327d038e5bef7e40dbaa7)

commit a2a04ea83d2960867324fa059ba1eedc2fc7784e (HEAD -> android-4.4)
Author: Mohan Srinivasan <[email protected]>
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 <[email protected]>

commit 32cbbe59538d2dd0b77822cc27ce32ca487c467d
Author: Mohan Srinivasan <[email protected]>
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 <[email protected]>
Loading

0 comments on commit a69f1ec

Please sign in to comment.