スキップしてメイン コンテンツに移動

filesystemio_optionsと非同期I/O

先日、filesystemio_options=asynchの場合のopenモードが不思議と書いたのですが、一応、サンプルソースを使って試してみました。
サンプルソースはLinux Foundationにあるaiocpを拝借してテストしました。

[oracle@kshinkub aio]$ wget http://devresources.linuxfoundation.org/daniel/AIO/aiocp.c
--2010-10-02 21:45:34--  http://devresources.linuxfoundation.org/daniel/AIO/aiocp.c
devresources.linuxfoundation.org をDNSに問いあわせています... 140.211.169.81
devresources.linuxfoundation.org|140.211.169.81|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 11896 (12K) [text/x-csrc]
`aiocp.c' に保存中

100%[==================================================================>] 11,896      37.3K/s 時間 0.3s

2010-10-02 18:45:35 (37.3 KB/s) - `aiocp.c' へ保存完了 [11896/11896]

[oracle@kshinkub aio]$ gcc -laio -o aiocp aiocp.c


処理内容はざっと以下の通りです。
1. コピー元ファイルのopen
2. コピー先ファイルのopen
3. 1に対してreadを非同期I/Oで要求し、その完了をコールバック関数で待ち受ける
4. 3のread要求が完了した場合、コールバック関数が呼ばれ、さらに2に対して非同期でwrite要求が発行される
5. write要求も完了時にはコールバック関数が呼ばれる
6. 全てのread/writeの要求が発行された場合、その完了を待って終了

つまり、処理の重いwriteの間に処理の軽いreadを多く発行させて、全体のスループットが上がることを期待したサンプルと言えます。以下、本当にそうなっているか確認してみます。
* 今回は、10MBのファイルを別ファイルにコピーするテストを実施しています。その際のブロックサイズはOracleのブロックサイズと合わせ8KBとしました。(別に合わす必要もないですが...)

1. 初期ファイルの作成(10MB)
[oracle@kshinkub aio]$ dd if=/dev/zero of=srcfile bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.0171325 seconds, 612 MB/s

2. ファイルキャシュクリア
[ora112d@RH5-64-112-node1-p ~]$ su - root -c "echo 3 > /proc/sys/vm/drop_caches"

3. O_SYNCの場合のAIO
[ora112d@RH5-64-112-node1-p ~]$ time ./aiocp -d -b 8K -f O_SYNC -f O_CREAT srcfile dstfile
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
(省略)
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
real    0m1.360s
user    0m0.002s
sys     0m0.123s

4. ファイルキャシュクリア
[ora112d@RH5-64-112-node1-p ~]$ su - root -c "echo 3 > /proc/sys/vm/drop_caches"

5. O_SYNC|O_DIRECTの場合のAIO
[ora112d@RH5-64-112-node1-p ~]$ time ./aiocp -d -b 8K -f O_SYNC -f O_DIRECT -f O_CREAT srcfile dstfile
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwrrrrrrr
rrrrrrrrrrrrrrrwwwwwwwwwwwwwrrrrrrwwrrrrrwwwwwwwwwwwwwwwrrrrrrrr
rrrrrwwwrrrrrwwwwrrrwwwrrrrwwwwwwwrrrrwwwwwwwwwwwwwwwwwwrrrrwwww
wwwwrrrrrrrrrrrrrrwwwwrrrwwwwwwwwwwwrrrrrrrrrrrrrwwwwwwwwwwwwwww
(省略)
rrrrrrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwrrrrwwww
real    0m0.403s
user    0m0.000s
sys     0m0.061s

"r"が出力(readが完了した時点)される条件は以下の通りです。

static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
(省略)  
        /* turn read into write */
        if (no_write) {
            --tocopy;
            --busy;
            free_iocb(iocb);
        } else {
            int fd;
            if (iocb->aio_fildes == srcfd)
                fd = dstfd;
            else
                fd = dstfd2;
            io_prep_pwrite(iocb, fd, buf, iosize, offset);
            io_set_callback(iocb, wr_done);
            if (1 != (res = io_submit(ctx, 1, &iocb)))
                io_error("io_submit write", res);
        }
        if (debug)
            write(2, "r", 1);
        if (debug > 1)
            printf("%d", iosize);
(省略)
}

つまり、io_submit(2)でread要求を発行し、そのコールバック関数rd_doneの中で、write用のio_submit(2)を発行し、そのwrite要求が成功した場合に"r"を出力しています。
O_DIRECTオプションを付けずにopenした場合は、"r"が続き、"w"が同数続いています。つまり、read完了後、write要求を出しているが 同期I/Oのため、次のread要求が出せないことを示しています。(非同期I/Oになっていない)
しかし、O_DIRECTオプション付きでopenした場合は、"r"が続き、更に"r"が続き、"w"が出てきて、途中で"r"が続き...のようになっています。これは、write要求のコールバック(完了)を待たずに、続けざまにreadを要求していることを示してます。
つまり、filesystemio_options=asynchとしても、openのモードにO_DIRECTが含まれていないので実際には同期I/Oとなっていると思われます。

仮にこの擬似コードの結果が正確なら、

非同期I/Oを使うには、filesystemio_optionsにsetallが必要ということになります。また、そうなるとファイルキャッシュは効き目なしになるので、それ相応のSGAの調整が必要になるということになります。(そもそもファイルキャッシュは当てにしていないですかね。。。)

コメント