先日、filesystemio_options=asynchの場合のopenモードが不思議と書いたのですが、一応、サンプルソースを使って試してみました。
サンプルソースはLinux Foundationにあるaiocpを拝借してテストしました。
処理内容はざっと以下の通りです。
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)
2. ファイルキャシュクリア
3. O_SYNCの場合のAIO
4. ファイルキャシュクリア
5. O_SYNC|O_DIRECTの場合のAIO
"r"が出力(readが完了した時点)される条件は以下の通りです。
つまり、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の調整が必要になるということになります。(そもそもファイルキャッシュは当てにしていないですかね。。。)
サンプルソースは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の調整が必要になるということになります。(そもそもファイルキャッシュは当てにしていないですかね。。。)
コメント
コメントを投稿