“fio” Flexible IO Tester post series from installing to a deep dive explanation and usage.
full course- FIO (Flexible I/O Tester) Part1 – Installation and compiling if needed
- FIO (Flexible I/O Tester) Part2 – First run and defining job files
- FIO (Flexible I/O Tester) Part3 – Environment variables and keywords
- FIO (Flexible I/O Tester) Part4 – fixed, ranges or finer grained block sizes?
- FIO (Flexible I/O Tester) Part5 – Direct I/O or buffered (page cache) or raw performance?
- FIO (Flexible I/O Tester) Part6 – Sequential read and readahead
- FIO (Flexible I/O Tester) Part7 – Steady State of SSD,NVMe,PCIe Flash with TKperf
- FIO (Flexible I/O Tester) Part8 – Interpret and understand the result/output
- FIO (Flexible I/O Tester) Part9 – fio2gnuplot to visualize the output
FIO is able to make us of environment variables and reserved keywords in job files. This can avoid some work so that you don“t need to change the job files each time you call them.
Define a variable in a job file
The documentation is pretty nice:
1 2 3 4 5 |
Any sub-string of the form "${VARNAME}" as part of an option value (in other words, on the right of the `='), will be expanded to the value of the environment variable called VARNAME. If no such environment variable is defined, or VARNAME is the empty string, the empty string will be substituted. |
So for example this is an entry in the job file where the size should be set via an environment variable.
1 |
size=${SIZE} |
Example of using environment variables
I would like to run four different job files and use for each run a different size (1MB,10MB,100MB,1G,10G,100G).
- Job1 is sequential read / 4 KB / 1 thread / ioengine=sync / iodepth=1
- Job2 is sequential write/ 4 KB / 1 thread / ioengine=sync / iodepth=1
- Job3 is random read / 4 KB / 1 thread / ioengine=sync / iodepth=1
- Job4 is random write / 4 KB / 1 thread / ioengine=sync / iodepth=1
I make use of the default settings under linux. For example I did not specify the block size which is 4K per default, but it is best practice to define them in case a default value may be changed.
Files:
jobfile1: read_4KB_numjob1_sync_iodepth1
1 2 3 4 5 |
[global] rw=read size=${SIZE} [read_4KB_numjob1_sync_iodepth1] |
jobfile2: write_4KB_numjob1_sync_iodepth1
1 2 3 4 5 |
[global] rw=write size=${SIZE} [write_4KB_numjob1_sync_iodepth1] |
jobfile3: randread_4KB_numjob1_sync_iodepth1
1 2 3 4 5 |
[global] rw=randread size=${SIZE} [randread_4KB_numjob1_sync_iodepth1] |
jobfile3: randwrite_4KB_numjob1_sync_iodepth1
1 2 3 4 5 |
[global] rw=randwrite size=${SIZE} [randwrite_4KB_numjob1_sync_iodepth1] |
Run fio:
1) Run with SIZE of 1M
1 |
SIZE=1M fio read_4KB_numjob1_sync_iodepth1 write_4KB_numjob1_sync_iodepth1 randread_4KB_numjob1_sync_iodepth1 randwrite_4KB_numjob1_sync_iodepth1 |
Yes this could be done in one job file but often you are using predefined files from a vendor or a website like this and just want to call them with your size settings.
2) Run with SIZE of 10M
1 |
SIZE=10M fio read_4KB_numjob1_sync_iodepth1 write_4KB_numjob1_sync_iodepth1 randread_4KB_numjob1_sync_iodepth1 randwrite_4KB_numjob1_sync_iodepth1 |
…. and so on.
Reserved keywords:
There are 3 documented reserved keywords:
- $pagesizeĀ Ā Ā Ā Ā Ā Ā Ā Ā The architecture page size of the running system
- $mb_memory Ā Ā Megabytes of total memory in the system
- $ncpusĀ Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Number of online available CPUs
You can use them in the command line or in the jobs files. They are substituted with the current system values when you run the job.
Use cases?
Lets say you would like to run a job with as much threads as online available CPUs.
file: read-x-threads
1 2 3 |
[read-x-threads] size=1M numjobs=$ncpus |
1 |
fio read-x-threads |
In my case (Testverse) there are 4 CPU cores with Hyper-Threading(HT) on. Means 8 threads.
Go Jenkins!