summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Velu <erwanaliasr1@gmail.com>2021-06-16 15:16:25 +0200
committerErwan Velu <erwanaliasr1@gmail.com>2021-06-27 23:15:24 +0200
commitd61215e076fe3b51c0ed92dd985101b84bbcd757 (patch)
treef4b9ce81549c3a2e0d4e32a5365bd72dc66c7805
parentd3dacdc61dfe878fda0c363084c4330492e38b2b (diff)
downloadfio-d61215e076fe3b51c0ed92dd985101b84bbcd757.tar.gz
fio-d61215e076fe3b51c0ed92dd985101b84bbcd757.tar.bz2
tools: Adding fiograph
This tool generates graphviz graphs of any fio job file. Reading a fio file can be sometimes tricky when : - you have lots of jobs - jobs override some options - jobs have dependencies Understanding which jobs are running at the same time, which one waits for which is sometimes difficult and could easily lead to mistakes. It's pretty common to find jobs where people think jobs are sequential while some run in parallel. For ease the understanding of the scheduling and what's the configuration status (local + global variables), this tool will use some graphical helpers to enlighten things. The configuration file can be used to adjust the rendering but by default : - jobs are defined in a blue rounded box - jobs running at the same time are inside the same gray background - time & size variables are shown as a self arrow - dependencies between jobs are shown by up->down black arrows - specific engines options are written in blue (top of the job box) - standard options are printed in green (bottom of the job box) - pre/post actions are printed in red (head/tail of the job box) - numjobs is replaced by a 'x' multiplicator on the job name Several output formats can be defined via --format : list can be found here https://graphviz.org/docs/outputs/ if --view option is used, the rendered file will be immediately shown. if --keep is used, the grapvhiz file will be kept. This commit also adds the rendering of the examples jobs. If a newcomer gets into the repository, they can immediately better understand what the jobs do. Signed-off-by: Erwan Velu <erwanaliasr1@gmail.com>
-rw-r--r--examples/1mbs_clients.pngbin0 -> 121336 bytes
-rw-r--r--examples/aio-read.pngbin0 -> 76819 bytes
-rw-r--r--examples/backwards-read.pngbin0 -> 31100 bytes
-rw-r--r--examples/basic-verify.pngbin0 -> 35952 bytes
-rw-r--r--examples/butterfly.pngbin0 -> 35393 bytes
-rw-r--r--examples/cpp_null.pngbin0 -> 34346 bytes
-rw-r--r--examples/cpuio.pngbin0 -> 52593 bytes
-rw-r--r--examples/cross-stripe-verify.pngbin0 -> 54366 bytes
-rw-r--r--examples/dev-dax.pngbin0 -> 93539 bytes
-rw-r--r--examples/dfs.pngbin0 -> 187461 bytes
-rw-r--r--examples/disk-zone-profile.pngbin0 -> 37313 bytes
-rw-r--r--examples/e4defrag.pngbin0 -> 97107 bytes
-rw-r--r--examples/e4defrag2.pngbin0 -> 222226 bytes
-rw-r--r--examples/enospc-pressure.pngbin0 -> 150373 bytes
-rw-r--r--examples/exitwhat.pngbin0 -> 111627 bytes
-rw-r--r--examples/falloc.pngbin0 -> 129273 bytes
-rw-r--r--examples/filecreate-ioengine.pngbin0 -> 59636 bytes
-rw-r--r--examples/filedelete-ioengine.pngbin0 -> 33042 bytes
-rw-r--r--examples/filestat-ioengine.pngbin0 -> 52330 bytes
-rw-r--r--examples/fio-rand-RW.pngbin0 -> 47406 bytes
-rw-r--r--examples/fio-rand-read.pngbin0 -> 36614 bytes
-rw-r--r--examples/fio-rand-write.pngbin0 -> 38608 bytes
-rw-r--r--examples/fio-seq-RW.pngbin0 -> 48279 bytes
-rw-r--r--examples/fio-seq-read.pngbin0 -> 37851 bytes
-rw-r--r--examples/fio-seq-write.pngbin0 -> 42756 bytes
-rw-r--r--examples/fixed-rate-submission.pngbin0 -> 41703 bytes
-rw-r--r--examples/flow.pngbin0 -> 63860 bytes
-rw-r--r--examples/fsx.pngbin0 -> 37310 bytes
-rw-r--r--examples/ftruncate.pngbin0 -> 56594 bytes
-rw-r--r--examples/gfapi.pngbin0 -> 46875 bytes
-rw-r--r--examples/gpudirect-rdmaio-client.pngbin0 -> 50659 bytes
-rw-r--r--examples/gpudirect-rdmaio-server.pngbin0 -> 37805 bytes
-rw-r--r--examples/http-s3.pngbin0 -> 108929 bytes
-rw-r--r--examples/http-swift.pngbin0 -> 113698 bytes
-rw-r--r--examples/http-webdav.pngbin0 -> 86857 bytes
-rw-r--r--examples/ime.pngbin0 -> 193722 bytes
-rw-r--r--examples/iometer-file-access-server.pngbin0 -> 44797 bytes
-rw-r--r--examples/jesd219.pngbin0 -> 64846 bytes
-rw-r--r--examples/latency-profile.pngbin0 -> 44487 bytes
-rw-r--r--examples/libcufile-cufile.pngbin0 -> 160611 bytes
-rw-r--r--examples/libcufile-posix.pngbin0 -> 164649 bytes
-rw-r--r--examples/libhdfs.pngbin0 -> 32812 bytes
-rw-r--r--examples/libiscsi.pngbin0 -> 31649 bytes
-rw-r--r--examples/libpmem.pngbin0 -> 119668 bytes
-rw-r--r--examples/librpma_apm-client.pngbin0 -> 53792 bytes
-rw-r--r--examples/librpma_apm-server.pngbin0 -> 42611 bytes
-rw-r--r--examples/librpma_gpspm-client.pngbin0 -> 56398 bytes
-rw-r--r--examples/librpma_gpspm-server.pngbin0 -> 53793 bytes
-rw-r--r--examples/libzbc-rand-write.pngbin0 -> 48503 bytes
-rw-r--r--examples/libzbc-seq-read.pngbin0 -> 47229 bytes
-rw-r--r--examples/mtd.pngbin0 -> 79866 bytes
-rw-r--r--examples/nbd.pngbin0 -> 88667 bytes
-rw-r--r--examples/netio.pngbin0 -> 50944 bytes
-rw-r--r--examples/netio_multicast.pngbin0 -> 74921 bytes
-rw-r--r--examples/nfs.pngbin0 -> 84808 bytes
-rw-r--r--examples/null.pngbin0 -> 30223 bytes
-rw-r--r--examples/numa.pngbin0 -> 66068 bytes
-rw-r--r--examples/pmemblk.pngbin0 -> 107529 bytes
-rw-r--r--examples/poisson-rate-submission.pngbin0 -> 41057 bytes
-rw-r--r--examples/rados.pngbin0 -> 39665 bytes
-rw-r--r--examples/rand-zones.pngbin0 -> 38297 bytes
-rw-r--r--examples/rbd.pngbin0 -> 37191 bytes
-rw-r--r--examples/rdmaio-client.pngbin0 -> 44671 bytes
-rw-r--r--examples/rdmaio-server.pngbin0 -> 31860 bytes
-rw-r--r--examples/ssd-steadystate.pngbin0 -> 71772 bytes
-rw-r--r--examples/ssd-test.pngbin0 -> 99835 bytes
-rw-r--r--examples/steadystate.pngbin0 -> 64580 bytes
-rw-r--r--examples/surface-scan.pngbin0 -> 72042 bytes
-rw-r--r--examples/test.pngbin0 -> 30141 bytes
-rw-r--r--examples/tiobench-example.pngbin0 -> 71939 bytes
-rw-r--r--examples/waitfor.pngbin0 -> 94577 bytes
-rw-r--r--examples/zbd-rand-write.pngbin0 -> 53018 bytes
-rw-r--r--examples/zbd-seq-read.pngbin0 -> 50185 bytes
-rw-r--r--examples/zipf.pngbin0 -> 33276 bytes
-rw-r--r--tools/fiograph/fiograph.conf102
-rwxr-xr-xtools/fiograph/fiograph.py305
76 files changed, 407 insertions, 0 deletions
diff --git a/examples/1mbs_clients.png b/examples/1mbs_clients.png
new file mode 100644
index 00000000..3f972dc6
--- /dev/null
+++ b/examples/1mbs_clients.png
Binary files differ
diff --git a/examples/aio-read.png b/examples/aio-read.png
new file mode 100644
index 00000000..e0c020a5
--- /dev/null
+++ b/examples/aio-read.png
Binary files differ
diff --git a/examples/backwards-read.png b/examples/backwards-read.png
new file mode 100644
index 00000000..81dc9208
--- /dev/null
+++ b/examples/backwards-read.png
Binary files differ
diff --git a/examples/basic-verify.png b/examples/basic-verify.png
new file mode 100644
index 00000000..98f73020
--- /dev/null
+++ b/examples/basic-verify.png
Binary files differ
diff --git a/examples/butterfly.png b/examples/butterfly.png
new file mode 100644
index 00000000..2c566512
--- /dev/null
+++ b/examples/butterfly.png
Binary files differ
diff --git a/examples/cpp_null.png b/examples/cpp_null.png
new file mode 100644
index 00000000..5303ac2a
--- /dev/null
+++ b/examples/cpp_null.png
Binary files differ
diff --git a/examples/cpuio.png b/examples/cpuio.png
new file mode 100644
index 00000000..02938dbb
--- /dev/null
+++ b/examples/cpuio.png
Binary files differ
diff --git a/examples/cross-stripe-verify.png b/examples/cross-stripe-verify.png
new file mode 100644
index 00000000..90aa630f
--- /dev/null
+++ b/examples/cross-stripe-verify.png
Binary files differ
diff --git a/examples/dev-dax.png b/examples/dev-dax.png
new file mode 100644
index 00000000..2463bca3
--- /dev/null
+++ b/examples/dev-dax.png
Binary files differ
diff --git a/examples/dfs.png b/examples/dfs.png
new file mode 100644
index 00000000..049ccaec
--- /dev/null
+++ b/examples/dfs.png
Binary files differ
diff --git a/examples/disk-zone-profile.png b/examples/disk-zone-profile.png
new file mode 100644
index 00000000..5f7b24c9
--- /dev/null
+++ b/examples/disk-zone-profile.png
Binary files differ
diff --git a/examples/e4defrag.png b/examples/e4defrag.png
new file mode 100644
index 00000000..00a7fefd
--- /dev/null
+++ b/examples/e4defrag.png
Binary files differ
diff --git a/examples/e4defrag2.png b/examples/e4defrag2.png
new file mode 100644
index 00000000..8a128e95
--- /dev/null
+++ b/examples/e4defrag2.png
Binary files differ
diff --git a/examples/enospc-pressure.png b/examples/enospc-pressure.png
new file mode 100644
index 00000000..da28b7c0
--- /dev/null
+++ b/examples/enospc-pressure.png
Binary files differ
diff --git a/examples/exitwhat.png b/examples/exitwhat.png
new file mode 100644
index 00000000..9fc1883f
--- /dev/null
+++ b/examples/exitwhat.png
Binary files differ
diff --git a/examples/falloc.png b/examples/falloc.png
new file mode 100644
index 00000000..886be22e
--- /dev/null
+++ b/examples/falloc.png
Binary files differ
diff --git a/examples/filecreate-ioengine.png b/examples/filecreate-ioengine.png
new file mode 100644
index 00000000..45d11da3
--- /dev/null
+++ b/examples/filecreate-ioengine.png
Binary files differ
diff --git a/examples/filedelete-ioengine.png b/examples/filedelete-ioengine.png
new file mode 100644
index 00000000..3512ab71
--- /dev/null
+++ b/examples/filedelete-ioengine.png
Binary files differ
diff --git a/examples/filestat-ioengine.png b/examples/filestat-ioengine.png
new file mode 100644
index 00000000..bed59ab9
--- /dev/null
+++ b/examples/filestat-ioengine.png
Binary files differ
diff --git a/examples/fio-rand-RW.png b/examples/fio-rand-RW.png
new file mode 100644
index 00000000..aa4b0998
--- /dev/null
+++ b/examples/fio-rand-RW.png
Binary files differ
diff --git a/examples/fio-rand-read.png b/examples/fio-rand-read.png
new file mode 100644
index 00000000..d45664a4
--- /dev/null
+++ b/examples/fio-rand-read.png
Binary files differ
diff --git a/examples/fio-rand-write.png b/examples/fio-rand-write.png
new file mode 100644
index 00000000..10e068bc
--- /dev/null
+++ b/examples/fio-rand-write.png
Binary files differ
diff --git a/examples/fio-seq-RW.png b/examples/fio-seq-RW.png
new file mode 100644
index 00000000..a2be35ec
--- /dev/null
+++ b/examples/fio-seq-RW.png
Binary files differ
diff --git a/examples/fio-seq-read.png b/examples/fio-seq-read.png
new file mode 100644
index 00000000..cf8f2978
--- /dev/null
+++ b/examples/fio-seq-read.png
Binary files differ
diff --git a/examples/fio-seq-write.png b/examples/fio-seq-write.png
new file mode 100644
index 00000000..8db12092
--- /dev/null
+++ b/examples/fio-seq-write.png
Binary files differ
diff --git a/examples/fixed-rate-submission.png b/examples/fixed-rate-submission.png
new file mode 100644
index 00000000..86ca9b3e
--- /dev/null
+++ b/examples/fixed-rate-submission.png
Binary files differ
diff --git a/examples/flow.png b/examples/flow.png
new file mode 100644
index 00000000..26a3d34c
--- /dev/null
+++ b/examples/flow.png
Binary files differ
diff --git a/examples/fsx.png b/examples/fsx.png
new file mode 100644
index 00000000..b4e13c80
--- /dev/null
+++ b/examples/fsx.png
Binary files differ
diff --git a/examples/ftruncate.png b/examples/ftruncate.png
new file mode 100644
index 00000000..b98895f6
--- /dev/null
+++ b/examples/ftruncate.png
Binary files differ
diff --git a/examples/gfapi.png b/examples/gfapi.png
new file mode 100644
index 00000000..acc6a6ae
--- /dev/null
+++ b/examples/gfapi.png
Binary files differ
diff --git a/examples/gpudirect-rdmaio-client.png b/examples/gpudirect-rdmaio-client.png
new file mode 100644
index 00000000..eac79858
--- /dev/null
+++ b/examples/gpudirect-rdmaio-client.png
Binary files differ
diff --git a/examples/gpudirect-rdmaio-server.png b/examples/gpudirect-rdmaio-server.png
new file mode 100644
index 00000000..e043d7c0
--- /dev/null
+++ b/examples/gpudirect-rdmaio-server.png
Binary files differ
diff --git a/examples/http-s3.png b/examples/http-s3.png
new file mode 100644
index 00000000..2021e85e
--- /dev/null
+++ b/examples/http-s3.png
Binary files differ
diff --git a/examples/http-swift.png b/examples/http-swift.png
new file mode 100644
index 00000000..9928fb16
--- /dev/null
+++ b/examples/http-swift.png
Binary files differ
diff --git a/examples/http-webdav.png b/examples/http-webdav.png
new file mode 100644
index 00000000..c37c3de5
--- /dev/null
+++ b/examples/http-webdav.png
Binary files differ
diff --git a/examples/ime.png b/examples/ime.png
new file mode 100644
index 00000000..f636f5e7
--- /dev/null
+++ b/examples/ime.png
Binary files differ
diff --git a/examples/iometer-file-access-server.png b/examples/iometer-file-access-server.png
new file mode 100644
index 00000000..e3124554
--- /dev/null
+++ b/examples/iometer-file-access-server.png
Binary files differ
diff --git a/examples/jesd219.png b/examples/jesd219.png
new file mode 100644
index 00000000..73b5a124
--- /dev/null
+++ b/examples/jesd219.png
Binary files differ
diff --git a/examples/latency-profile.png b/examples/latency-profile.png
new file mode 100644
index 00000000..50650df8
--- /dev/null
+++ b/examples/latency-profile.png
Binary files differ
diff --git a/examples/libcufile-cufile.png b/examples/libcufile-cufile.png
new file mode 100644
index 00000000..f3758e5d
--- /dev/null
+++ b/examples/libcufile-cufile.png
Binary files differ
diff --git a/examples/libcufile-posix.png b/examples/libcufile-posix.png
new file mode 100644
index 00000000..7818feb4
--- /dev/null
+++ b/examples/libcufile-posix.png
Binary files differ
diff --git a/examples/libhdfs.png b/examples/libhdfs.png
new file mode 100644
index 00000000..e774c911
--- /dev/null
+++ b/examples/libhdfs.png
Binary files differ
diff --git a/examples/libiscsi.png b/examples/libiscsi.png
new file mode 100644
index 00000000..d0006cc0
--- /dev/null
+++ b/examples/libiscsi.png
Binary files differ
diff --git a/examples/libpmem.png b/examples/libpmem.png
new file mode 100644
index 00000000..8a9a1432
--- /dev/null
+++ b/examples/libpmem.png
Binary files differ
diff --git a/examples/librpma_apm-client.png b/examples/librpma_apm-client.png
new file mode 100644
index 00000000..2fe02cdf
--- /dev/null
+++ b/examples/librpma_apm-client.png
Binary files differ
diff --git a/examples/librpma_apm-server.png b/examples/librpma_apm-server.png
new file mode 100644
index 00000000..f78ae02e
--- /dev/null
+++ b/examples/librpma_apm-server.png
Binary files differ
diff --git a/examples/librpma_gpspm-client.png b/examples/librpma_gpspm-client.png
new file mode 100644
index 00000000..0c975a27
--- /dev/null
+++ b/examples/librpma_gpspm-client.png
Binary files differ
diff --git a/examples/librpma_gpspm-server.png b/examples/librpma_gpspm-server.png
new file mode 100644
index 00000000..56124533
--- /dev/null
+++ b/examples/librpma_gpspm-server.png
Binary files differ
diff --git a/examples/libzbc-rand-write.png b/examples/libzbc-rand-write.png
new file mode 100644
index 00000000..1d277412
--- /dev/null
+++ b/examples/libzbc-rand-write.png
Binary files differ
diff --git a/examples/libzbc-seq-read.png b/examples/libzbc-seq-read.png
new file mode 100644
index 00000000..5a532228
--- /dev/null
+++ b/examples/libzbc-seq-read.png
Binary files differ
diff --git a/examples/mtd.png b/examples/mtd.png
new file mode 100644
index 00000000..8cb3692e
--- /dev/null
+++ b/examples/mtd.png
Binary files differ
diff --git a/examples/nbd.png b/examples/nbd.png
new file mode 100644
index 00000000..e3bcf610
--- /dev/null
+++ b/examples/nbd.png
Binary files differ
diff --git a/examples/netio.png b/examples/netio.png
new file mode 100644
index 00000000..81afd41d
--- /dev/null
+++ b/examples/netio.png
Binary files differ
diff --git a/examples/netio_multicast.png b/examples/netio_multicast.png
new file mode 100644
index 00000000..f07ab4b7
--- /dev/null
+++ b/examples/netio_multicast.png
Binary files differ
diff --git a/examples/nfs.png b/examples/nfs.png
new file mode 100644
index 00000000..29dbca0d
--- /dev/null
+++ b/examples/nfs.png
Binary files differ
diff --git a/examples/null.png b/examples/null.png
new file mode 100644
index 00000000..052671db
--- /dev/null
+++ b/examples/null.png
Binary files differ
diff --git a/examples/numa.png b/examples/numa.png
new file mode 100644
index 00000000..1ef45759
--- /dev/null
+++ b/examples/numa.png
Binary files differ
diff --git a/examples/pmemblk.png b/examples/pmemblk.png
new file mode 100644
index 00000000..250e254b
--- /dev/null
+++ b/examples/pmemblk.png
Binary files differ
diff --git a/examples/poisson-rate-submission.png b/examples/poisson-rate-submission.png
new file mode 100644
index 00000000..739c2560
--- /dev/null
+++ b/examples/poisson-rate-submission.png
Binary files differ
diff --git a/examples/rados.png b/examples/rados.png
new file mode 100644
index 00000000..91bd61a0
--- /dev/null
+++ b/examples/rados.png
Binary files differ
diff --git a/examples/rand-zones.png b/examples/rand-zones.png
new file mode 100644
index 00000000..13cbfb47
--- /dev/null
+++ b/examples/rand-zones.png
Binary files differ
diff --git a/examples/rbd.png b/examples/rbd.png
new file mode 100644
index 00000000..f1186139
--- /dev/null
+++ b/examples/rbd.png
Binary files differ
diff --git a/examples/rdmaio-client.png b/examples/rdmaio-client.png
new file mode 100644
index 00000000..4e4bc289
--- /dev/null
+++ b/examples/rdmaio-client.png
Binary files differ
diff --git a/examples/rdmaio-server.png b/examples/rdmaio-server.png
new file mode 100644
index 00000000..fc344725
--- /dev/null
+++ b/examples/rdmaio-server.png
Binary files differ
diff --git a/examples/ssd-steadystate.png b/examples/ssd-steadystate.png
new file mode 100644
index 00000000..eb27f8a4
--- /dev/null
+++ b/examples/ssd-steadystate.png
Binary files differ
diff --git a/examples/ssd-test.png b/examples/ssd-test.png
new file mode 100644
index 00000000..a92ed153
--- /dev/null
+++ b/examples/ssd-test.png
Binary files differ
diff --git a/examples/steadystate.png b/examples/steadystate.png
new file mode 100644
index 00000000..4bb90484
--- /dev/null
+++ b/examples/steadystate.png
Binary files differ
diff --git a/examples/surface-scan.png b/examples/surface-scan.png
new file mode 100644
index 00000000..00573808
--- /dev/null
+++ b/examples/surface-scan.png
Binary files differ
diff --git a/examples/test.png b/examples/test.png
new file mode 100644
index 00000000..6be50029
--- /dev/null
+++ b/examples/test.png
Binary files differ
diff --git a/examples/tiobench-example.png b/examples/tiobench-example.png
new file mode 100644
index 00000000..14410326
--- /dev/null
+++ b/examples/tiobench-example.png
Binary files differ
diff --git a/examples/waitfor.png b/examples/waitfor.png
new file mode 100644
index 00000000..64e4bf94
--- /dev/null
+++ b/examples/waitfor.png
Binary files differ
diff --git a/examples/zbd-rand-write.png b/examples/zbd-rand-write.png
new file mode 100644
index 00000000..d58721be
--- /dev/null
+++ b/examples/zbd-rand-write.png
Binary files differ
diff --git a/examples/zbd-seq-read.png b/examples/zbd-seq-read.png
new file mode 100644
index 00000000..b81a08c4
--- /dev/null
+++ b/examples/zbd-seq-read.png
Binary files differ
diff --git a/examples/zipf.png b/examples/zipf.png
new file mode 100644
index 00000000..cb2a9816
--- /dev/null
+++ b/examples/zipf.png
Binary files differ
diff --git a/tools/fiograph/fiograph.conf b/tools/fiograph/fiograph.conf
new file mode 100644
index 00000000..7b851e19
--- /dev/null
+++ b/tools/fiograph/fiograph.conf
@@ -0,0 +1,102 @@
+[fio_jobs]
+header=<<B><font color="{}"> {} </font></B> >
+header_color=black
+text_color=darkgreen
+shape=box
+shape_color=blue
+style=rounded
+title_style=<<table border='0' cellborder='0' cellspacing='1'> <tr> <td align='center'> <b> {} </b> </td> </tr>
+item_style=<tr> <td align = "left"> <font color="{}" > {} </font> </td> </tr>
+cluster_style=filled
+cluster_color=gainsboro
+
+[exec_prerun]
+text_color=red
+
+[exec_postrun]
+text_color=red
+
+[numjobs]
+text_color=red
+style=<font color="{}" > x {} </font>
+
+[ioengine]
+text_color=darkblue
+specific_options_color=darkblue
+
+# definitions of engine's specific options
+
+[ioengine_cpuio]
+specific_options=cpuload cpumode cpuchunks exit_on_io_done
+
+[ioengine_dfs]
+specific_options=pool cont chunk_size object_class svcl
+
+[ioengine_e4defrag]
+specific_options=donorname inplace
+
+[ioengine_filestat]
+specific_options=stat_type
+
+[ioengine_single-instance]
+specific_options=volume brick
+
+[ioengine_http]
+specific_options=https http_host http_user http_pass http_s3_key http_s3_keyid http_swift_auth_token http_s3_region http_mode http_verbose
+
+[ioengine_ime_aio]
+specific_options=ime_psync ime_psyncv
+
+[ioengine_io_uring]
+specific_options=hipri cmdprio_percentage cmdprio_percentage fixedbufs registerfiles sqthread_poll sqthread_poll_cpu nonvectored uncached nowait force_async
+
+[ioengine_libaio]
+specific_options=userspace_reap cmdprio_percentage cmdprio_percentage nowait
+
+[ioengine_libcufile]
+specific_options=gpu_dev_ids cuda_io
+
+[ioengine_libhdfs]
+specific_options=namenode hostname port hdfsdirectory chunk_size single_instance hdfs_use_direct
+
+[ioengine_libiscsi]
+specific_options=initiator
+
+[ioengine_librpma_apm_server]
+specific_options=librpma_apm_client
+
+[ioengine_busy_wait_polling]
+specific_options=serverip port direct_write_to_pmem
+
+[ioengine_librpma_gpspm_server]
+specific_options=librpma_gpspm_client
+
+[ioengine_mmap]
+specific_options=thp
+
+[ioengine_mtd]
+specific_options=skip_bad
+
+[ioengine_nbd]
+specific_options=uri
+
+[ioengine_net]
+specific_options=hostname port protocol nodelay listen pingpong interface ttl window_size mss netsplice
+
+[ioengine_nfs]
+specific_options=nfs_url
+
+[ioengine_rados]
+specific_options=clustername pool clientname busy_poll touch_objects
+
+[ioengine_rbd]
+specific_options=clustername rbdname pool clientname busy_poll
+
+[ioengine_rdma]
+specific_options=hostname bindname port verb
+
+[ioengine_sg]
+specific_options=hipri readfua writefua sg_write_mode sg
+
+[ioengine_pvsync2]
+specific_options=hipri hipri_percentage uncached nowait sync psync vsync pvsync
diff --git a/tools/fiograph/fiograph.py b/tools/fiograph/fiograph.py
new file mode 100755
index 00000000..7695c964
--- /dev/null
+++ b/tools/fiograph/fiograph.py
@@ -0,0 +1,305 @@
+#!/usr/bin/env python3
+from graphviz import Digraph
+import argparse
+import configparser
+import os
+
+config_file = None
+fio_file = None
+
+
+def get_section_option(section_name, option_name, default=None):
+ global fio_file
+ if fio_file.has_option(section_name, option_name):
+ return fio_file[section_name][option_name]
+ return default
+
+
+def get_config_option(section_name, option_name, default=None):
+ global config_file
+ if config_file.has_option(section_name, option_name):
+ return config_file[section_name][option_name]
+ return default
+
+
+def get_header_color(keyword='fio_jobs', default_color='black'):
+ return get_config_option(keyword, 'header_color', default_color)
+
+
+def get_shape_color(keyword='fio_jobs', default_color='black'):
+ return get_config_option(keyword, 'shape_color', default_color)
+
+
+def get_text_color(keyword='fio_jobs', default_color='black'):
+ return get_config_option(keyword, 'text_color', default_color)
+
+
+def get_cluster_color(keyword='fio_jobs', default_color='gray92'):
+ return get_config_option(keyword, 'cluster_color', default_color)
+
+
+def get_header(keyword='fio_jobs'):
+ return get_config_option(keyword, 'header')
+
+
+def get_shape(keyword='fio_jobs'):
+ return get_config_option(keyword, 'shape', 'box')
+
+
+def get_style(keyword='fio_jobs'):
+ return get_config_option(keyword, 'style', 'rounded')
+
+
+def get_cluster_style(keyword='fio_jobs'):
+ return get_config_option(keyword, 'cluster_style', 'filled')
+
+
+def get_specific_options(engine):
+ if not engine:
+ return ''
+ return get_config_option('ioengine_{}'.format(engine), 'specific_options', '').split(' ')
+
+
+def render_option(section, label, display, option, color_override=None):
+ # These options are already shown with graphical helpers, no need to report them directly
+ skip_list = ['size', 'stonewall', 'runtime', 'time_based',
+ 'numjobs', 'wait_for', 'wait_for_previous']
+ # If the option doesn't exist or if a special handling is already done
+ # don't render it, just return the current state
+ if option in skip_list or option not in section:
+ return label, display
+ display = option
+ if section[option]:
+ display = '{} = {}'.format(display, section[option])
+
+ # Adding jobs's options into the box, darkgreen is the default color
+ if color_override:
+ color = color_override
+ else:
+ color = get_text_color(option, get_text_color('fio_jobs', 'darkgreen'))
+ label += get_config_option('fio_jobs',
+ 'item_style').format(color, display)
+ return label, display
+
+
+def render_options(fio_file, section_name):
+ """Render all options of a section."""
+ display = section_name
+ section = fio_file[section_name]
+
+ # Add a multiplier to the section_name if numjobs is set
+ numjobs = int(get_section_option(section_name, 'numjobs', '1'))
+ if numjobs > 1:
+ display = display + \
+ get_style('numjobs').format(
+ get_text_color('numjobs'), numjobs)
+
+ # Header of the box
+ label = get_config_option('fio_jobs', 'title_style').format(display)
+
+ # Let's parse all the options of the current fio thread
+ # Some needs to be printed on top or bottom of the job to ease the read
+ to_early_print = ['exec_prerun', 'ioengine']
+ to_late_print = ['exec_postrun']
+
+ # Let's print the options on top of the box
+ for early_print in to_early_print:
+ label, display = render_option(
+ section, label, display, early_print)
+
+ current_io_engine = get_section_option(
+ section_name, 'ioengine', None)
+ if current_io_engine:
+ # Let's print all specifics options for this engine
+ for specific_option in sorted(get_specific_options(current_io_engine)):
+ label, display = render_option(
+ section, label, display, specific_option, get_config_option('ioengine', 'specific_options_color'))
+
+ # Let's print generic options sorted by name
+ for option in sorted(section):
+ if option in to_early_print or option in to_late_print or option in get_specific_options(current_io_engine):
+ continue
+ label, display = render_option(section, label, display, option)
+
+ # let's print options on the bottom of the box
+ for late_print in to_late_print:
+ label, display = render_option(
+ section, label, display, late_print)
+
+ # End of the box content
+ label += '</table>>'
+ return label
+
+
+def render_section(current_graph, fio_file, section_name, label):
+ """Render the section."""
+ attr = None
+ section = fio_file[section_name]
+
+ # Let's render the box associated to a job
+ current_graph.node(section_name, label,
+ shape=get_shape(),
+ color=get_shape_color(),
+ style=get_style())
+
+ # Let's report the duration of the jobs with a self-loop arrow
+ if 'runtime' in section and 'time_based' in section:
+ attr = 'runtime={}'.format(section['runtime'])
+ elif 'size' in section:
+ attr = 'size={}'.format(section['size'])
+ if attr:
+ current_graph.edge(section_name, section_name, attr)
+
+
+def create_sub_graph(name):
+ """Return a new graph."""
+ # We need to put 'cluster' in the name to ensure graphviz consider it as a cluster
+ cluster_name = 'cluster_' + name
+ # Unset the main graph labels to avoid a recopy in each subgraph
+ attr = {}
+ attr['label'] = ''
+ new_graph = Digraph(name=cluster_name, graph_attr=attr)
+ new_graph.attr(style=get_cluster_style(),
+ color=get_cluster_color())
+ return new_graph
+
+
+def create_legend():
+ """Return a legend."""
+ html_table = "<<table border='0' cellborder='1' cellspacing='0' cellpadding='4'>"
+ html_table += '<tr><td COLSPAN="2"><b>Legend</b></td></tr>'
+ legend_item = '<tr> <td>{}</td> <td><font color="{}">{}</font></td></tr>"'
+ legend_bgcolor_item = '<tr><td>{}</td><td BGCOLOR="{}"></td></tr>'
+ html_table += legend_item.format('numjobs',
+ get_text_color('numjobs'), 'x numjobs')
+ html_table += legend_item.format('generic option',
+ get_text_color(), 'generic option')
+ html_table += legend_item.format('ioengine option',
+ get_text_color('ioengine'), 'ioengine option')
+ html_table += legend_bgcolor_item.format('job', get_shape_color())
+ html_table += legend_bgcolor_item.format(
+ 'execution group', get_cluster_color())
+ html_table += '</table>>'
+ legend = Digraph('html_table')
+ legend.node('legend', shape='none', label=html_table)
+ return legend
+
+
+def fio_to_graphviz(filename, format):
+ """Compute the graphviz graph from the fio file."""
+
+ # Let's read the fio file
+ global fio_file
+ fio_file = configparser.RawConfigParser(
+ allow_no_value=True,
+ default_section="global",
+ inline_comment_prefixes="'#', ';'")
+ fio_file.read(filename)
+
+ # Prepare the main graph object
+ # Let's define the header of the document
+ attrs = {}
+ attrs['labelloc'] = 't'
+ attrs['label'] = get_header().format(
+ get_header_color(), os.path.basename(filename))
+ main_graph = Digraph(engine='dot', graph_attr=attrs, format=format)
+
+ # Let's add a legend
+ main_graph.subgraph(create_legend())
+
+ # By default all jobs are run in parallel and depends on "global"
+ depends_on = fio_file.default_section
+
+ # The previous section is by default the global section
+ previous_section = fio_file.default_section
+
+ current_graph = main_graph
+
+ # The first job will be a new execution group
+ new_execution_group = True
+
+ # Let's interate on all sections to create links between them
+ for section_name in fio_file.sections():
+ # The current section
+ section = fio_file[section_name]
+
+ # If the current section is waiting the previous job
+ if ('stonewall' or 'wait_for_previous') in section:
+ # let's remember what was the previous job we depend on
+ depends_on = previous_section
+ new_execution_group = True
+ elif 'wait_for' in section:
+ # This sections depends on a named section pointed by wait_for
+ depends_on = section['wait_for']
+ new_execution_group = True
+
+ if new_execution_group:
+ # Let's link the current graph with the main one
+ main_graph.subgraph(current_graph)
+ # Let's create a new graph to represent all the incoming jobs running at the same time
+ current_graph = create_sub_graph(section_name)
+
+ # Let's render the current section in its execution group
+ render_section(current_graph, fio_file, section_name,
+ render_options(fio_file, section_name))
+
+ # Let's trace the link between this job and the one it depends on
+ # If we depend on 'global', we can avoid doing adding an arrow as we don't want to see 'global'
+ if depends_on != fio_file.default_section:
+ current_graph.edge(depends_on, section_name)
+
+ # The current section become the parent of the next one
+ previous_section = section_name
+
+ # We are by default in the same execution group
+ new_execution_group = False
+
+ # The last subgraph isn't rendered yet
+ main_graph.subgraph(current_graph)
+
+ # Let's return the main graphviz object
+ return main_graph
+
+
+def setup_commandline():
+ "Prepare the command line."
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--file', action='store',
+ type=str,
+ required=True,
+ help='the fio file to graph')
+ parser.add_argument('--output', action='store',
+ type=str,
+ help='the output filename')
+ parser.add_argument('--format', action='store',
+ type=str,
+ default='png',
+ help='the output format')
+ parser.add_argument('--view', action='store_true',
+ default=False,
+ help='view the graph')
+ parser.add_argument('--keep', action='store_true',
+ default=False,
+ help='keep the graphviz script file')
+ parser.add_argument('--config', action='store',
+ type=str,
+ default='fiograph.conf',
+ help='the configuration filename')
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ global config_file
+ args = setup_commandline()
+ output_file = args.file
+ if args.output is None:
+ output_file = output_file.replace('.fio', '')
+ config_file = configparser.RawConfigParser(allow_no_value=True)
+ config_file.read(args.config)
+ fio_to_graphviz(args.file, args.format).render(output_file, view=args.view)
+ if not args.keep:
+ os.remove(output_file)
+
+
+main()