FIO基准测试如何设置IO深度?

FIO基准测试如何设置IO深度?

笔记: 我的问题源于另一个 U&L Q -fio中的iodepth到底是什么?


我想知道内部如何菲奥设置 I/O 深度。即,当我们运行FIO时,我们提交给FIO的参数之一是“IO深度”( --iodepth=)。 FIO内部是如何通过底层操作系统来控制这个参数的呢?

以下是我们用来运行 FIO 基准测试的命令示例:

$ sudo fio --filename=/dev/nvme0n1 --direct=1 --rw=randwrite --refill_buffers \
    --norandommap --randrepeat=0 --ioengine=libaio --bs=8K--io深度=72--numjobs=256 \
    --time_based --runtime=600 --allow_mounted_write=1 --group_reporting --name=benchtest
基准测试:(g=0):rw=randwrite,bs=8K-8K/8K-8K/8K-8K,ioengine=libaio,io深度=72

如本例所示,“iodepth”的值可以更改。因此,fio 将此值传递给操作系统。那么FIO是如何做到这一点的呢?

如果你想解决一个实际问题:如果我想写一个像fio这样的基准程序,我该如何控制IO队列深度?

答案1

fio 正在将此值 [深度] 传递给操作系统

因此,fio 将此值传递给操作系统。那么FIO是如何做到这一点的呢?

这里可能存在误解:fio 并不直接将深度参数传递给操作系统。如果可能,fio 尝试iodepth使用给定的 ioengine 提交指定的 I/O。如果达到深度然后fio 将等待(某些)未完成的 I/O 完成,然后再尝试提交更多 I/O...

FIO 基准测试如何设置 [io]深度?

取决于ioengine,取决于中提到的fio参数fio中的iodepth到底是什么?,https://serverfault.com/questions/923487/what-does-iodepth-in-fio-tests-really-mean-is-it-the-queue-depthhttps://www.spinics.net/lists/fio/msg07191.html。如果没有小的固定例子,就有太多的东西需要解释。

到了某个时候,除了阅读和理解 fio 本身的代码之外,没有其他事可做... Fio 有用于提交 I/O 的主循环(请参阅https://github.com/axboe/fio/blob/fio-3.8/backend.c#L1055):

static void do_io(struct thread_data *td, uint64_t *bytes_done)
{
    [...]
    while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
        (!flist_empty(&td->trim_list)) || !io_issue_bytes_exceeded(td) ||
        td->o.time_based) {
        [...]
        } else {
            ret = io_u_submit(td, io_u);

            if (should_check_rate(td))
                td->rate_next_io_time[ddir] = usec_for_io(td, ddir);

            if (io_queue_event(td, io_u, &ret, ddir, &bytes_issued, 0, &comp_time))
                break;

            /*
             * See if we need to complete some commands. Note that
             * we can get BUSY even without IO queued, if the
             * system is resource starved.
             */
reap:
            full = queue_full(td) ||
                (ret == FIO_Q_BUSY && td->cur_depth);
            if (full || io_in_polling(td))
                ret = wait_for_completions(td, &comp_time);
        }
        [...]
    }
    [...]
}

ioengine 的排队例程由来自 的调用链调用io_u_submit()。假设 ioengine 是异步的,它可能会选择只在 fio 中“排队”I/O,然后在稍后一次性提交整个 I/O(通常是getevents()从调用链调用其函数的结果wait_for_completions())。不过,我们将通过 fio 的代码进行跟踪作为读者的练习。

如果我想写一个像fio这样的基准程序,我该如何控制IO队列深度?

您需要模仿 fio 的(异步)ioengine 之一,并拥有一个能够(异步)提交 I/O 并检查其完成情况的事件循环。一旦你有了这样的想法,你只提交特定深度的想法就会很容易 - 如果在任何时候你都有未完成的 I/O 匹配(或者超过,如果你不逐一检查)所选深度那么您需要等待某些内容完成才能提交更多内容。

你可能会发现Linux 测试项目中的 aio-stress.c如果您正在制作玩具基准测试,则比 fio 更容易理解/修改。

相关内容