ASMLibに関する検証 その6
<ASMLibに関する検証 その6>
ペンネーム: ソラ
今回も引き続き、ASMLib Kernel Driver(以下、ASMLib)に関する検証を行いま
す。
■前回のおさらい
前回は、ASMLibのメリット「I/O処理の効率がよくなる」について、ディスク
からの読み込みと書き込みに関連する処理を、SELECT文(ディスクからの読み
込み)とINSERT文(ディスクへの書き込み)の場合での効果を実行時間で測定し
ました。
検証の結果、ASMLibを使用することで、ディスクへの書き込み(INSERT文)が少
し高速化することがわかりました。
それでは、なぜ高速化するのか検証していきたいと思います。
■■■■■概要■■■■■
1.調査項目
2.インスタンスのOPEN時にDBWRが発行するシステムコール
3.INSERT文実行時のDBWRが発行するシステムコール
4.ASMLibに関する検証のまとめ
■検証環境
Red Hat Enterprise Linux Server release 5
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0
1.調査項目
高速化した理由について、まずは、RAWデバイスとASMLibを使用している場合
での違いから探します。
INSERT文のようなデータをディスクに書き込む処理と関連性の高いバックグラ
ウンド・プロセスはDBWRとLGWRです。
本検証では、以下の2つの状況でDBWRプロセスが発行しているシステムコール
の違いに着目して調査します。
状況1:インスタンスのOPEN時(データファイルのオープン時)
状況2:INSERT文実行時
2.インスタンスのOPEN時にDBWRが発行するシステムコール
以下、straceコマンドを使用して、インスタンスのOPEN時にDBWRが発行したシ
ステムコールを確認した結果、大きく違いが見られた部分です。
RAWデバイスの場合 open("/dev/raw/raw1", O_RDWR|O_SYNC) = 19 fcntl(19, F_SETFD, FD_CLOEXEC) = 0 ASMLibの場合 open("/opt/oracle/extapi/64/asm/orcl/1/libasm.so", O_RDONLY) = 19 read(19, "177ELF2113>1 21 "..., 832) = 832 fstat(19, {st_mode=S_IFREG|0755, st_size=18176, ...}) = 0 mmap(NULL, 2113432, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 19, 0) = 0x2ac1aca92000 mprotect(0x2ac1aca96000, 2093056, PROT_NONE) = 0 mmap(0x2ac1acc95000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED |MAP_DENYWRITE, 19, 0x3000) = 0x2ac1acc95000 close(19) = 0 open("/dev/oracleasm/.check_iid", O_RDWR) = 19 write(19, "MSA233023", 24) = 24 read(19, "MSA233023", 24) = 24 close(19) = 0 000019> open("/dev/oracleasm/iid/0000000000000013", O_RDWR|O_CREAT, 0770) = 19 fcntl(19, F_GETFD) = 0 fcntl(19, F_SETFD, FD_CLOEXEC) = 0
大きく違う部分としては以下の2点です。
1.libasm.soのopenの有無
2.データファイルのopenシステムコール発行時のO_SYNCオプション
1つめのlibasm.soは、ASMLibをインストールした際に配置されるファイル
です。
そのため、ASMLibの動作に必要なライブラリを使用可能にしているだけのため
ASMLibを使用する環境としては当然の動作です。
2つめについて、O_SYNCオプションを使用している場合は同期モードでデータ
ファイルのopenすることになります。
また、オプションを使用していない場合では非同期モードでファイルをopenす
ることになります。
つまり、ASMLibの場合は非同期モードでファイルをopenしているために高速化
しているということなのでしょうか?
実際にその仮説が正しいのか判断するために、まずはOSのシステムコールだけ
で考えた場合、同期モードと非同期モードではどのくらい違いが出てくるのか
を知る必要があります。
ということで、実際に確認します。
以下、確認に使用したスクリプトです。
<同期モード確認用スクリプト> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #define BUF_SIZE 0x500000 int main(int argc, char **argv) { char buf[BUF_SIZE + 1]; int count = 0; int fd; int i; if (argc != 2) { printf("Usage: $ ./sync 100(write count)n"); return -1; } count = atoi(argv[1]); if (count < 1) { printf("Usage: $ ./sync 100(write count)n"); return -1; } fd = open("file1", O_CREAT | O_WRONLY | O_SYNC, S_IRUSR | S_IWUSR); if (fd == -1) { printf("failed to open:errno=%dn", errno); return -1; } memset(buf, 1, BUF_SIZE); buf[BUF_SIZE] = ''; for (i = 0; i < count; i++) { write(fd, buf, BUF_SIZE); } close(fd); return 0; } <非同期モード確認用スクリプト> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #define BUF_SIZE 0x500000 int main(int argc, char **argv) { char buf[BUF_SIZE + 1]; int count = 0; int fd; int i; if (argc != 2) { printf("Usage: $ ./sync 100(write count)n"); return -1; } count = atoi(argv[1]); if (count < 1) { printf("Usage: $ ./sync 100(write count)n"); return -1; } fd = open("file2", O_CREAT | O_WRONLY , S_IRUSR | S_IWUSR); if (fd == -1) { printf("failed to open:errno=%dn", errno); return -1; } memset(buf, 1, BUF_SIZE); buf[BUF_SIZE] = ''; for (i = 0; i < count; i++) { write(fd, buf, BUF_SIZE); } close(fd); return 0; }
以下は上記スクリプトの第一引数に20を渡し、それぞれ5MBの書き込みを
行った際の実行時間です。
<同期モード> real 0m2.886s user 0m0.000s sys 0m0.268s <非同期モード> real 0m0.361s user 0m0.001s sys 0m0.360s
上記のように同期モードと非同期モードでは2秒以上差が出る結果になりました。
前回のINSERT文での検証ではこれ以上の書き込みを行っているにも関わらず、
実行時間に差が上記ほど見られないことから、単純にファイルのopenの仕方が
同期モードか、非同期モードであるかという説明では納得しにくいことがわか
ります。
3.INSERT文実行時のDBWRが発行するシステムコール
それでは次に、INSERT文実行時のシステムコールを確認します。
straceコマンドを使用して確認した結果、発行されているシステムコール自体
に違いが見られたので結果の一部を抜粋します。
======================straceコマンドの結果============================ RAWデバイスを使用している場合 io_submit(47418402635776, 6, { {0x2b207560e1a0, 0, 1, 0, 19}, {0x2b207560d7a0, 0, 1, 0, 19}, {0x2b207560d1a0, 0, 1, 0, 19}, {0x2b207560d9a0, 0, 1, 0, 19}, {0x2b207560dfa0, 0, 1, 0, 19}, {0x2b207560d3a0, 0, 1, 0, 19}}) = 6 io_getevents(47418402635776, 4, 128, { {0x2b207560e1a0, 0x2b207560e1a0, 212992, 0}, {0x2b207560d3a0, 0x2b207560d3a0, 8192, 0}, {0x2b207560dfa0, 0x2b207560dfa0, 8192, 0}, {0x2b207560d1a0, 0x2b207560d1a0, 344064, 0}}, {600, 0}) = 4 times(NULL) = 500725677 io_submit(47418402635776, 8, { {0x2b207560d1a0, 0, 1, 0, 19}, {0x2b207560dfa0, 0, 1, 0, 19}, {0x2b207560d3a0, 0, 1, 0, 19}, {0x2b207560e1a0, 0, 1, 0, 19}, {0x2b207560dda0, 0, 1, 0, 19}, {0x2b207560c5a0, 0, 1, 0, 19}, {0x2b207560c7a0, 0, 1, 0, 19}, {0x2b207560e5a0, 0, 1, 0, 19}}) = 8 io_getevents(47418402635776, 10, 128, { {0x2b207560dda0, 0x2b207560dda0, 212992, 0}, {0x2b207560c7a0, 0x2b207560c7a0, 212992, 0}, {0x2b207560d7a0, 0x2b207560d7a0, 704512, 0}, {0x2b207560d9a0, 0x2b207560d9a0, 704512, 0}, {0x2b207560c5a0, 0x2b207560c5a0, 835584, 0}, {0x2b207560e1a0, 0x2b207560e1a0, 704512, 0}, {0x2b207560e5a0, 0x2b207560e5a0, 835584, 0}, {0x2b207560d3a0, 0x2b207560d3a0, 8192, 0}, {0x2b207560d1a0, 0x2b207560d1a0, 8192, 0}, {0x2b207560dfa0, 0x2b207560dfa0, 8192, 0}}, {600, 0}) = 10 ASMLibを使用している場合 read(19, "MSA