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, "MSA210P00027636220240
  244254301*"..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
read(19, "MSA210P00027636220
  "..., 80) = 80
times(NULL)                             = 500826381

======================================================================

上記のシステムコールではデータファイルへの書き込みはできません。
ただ、RAWデバイスとASMLibを使用している場合では、DBWRが発行しているシ
ステムコールから動作が全く違うということから推測すると、実際に書き込み
を行っている部分でも上記のように全く異なる書き込み方法を行っている可能
性が高そうです。
そのため、そもそも行っている処理が違うために、INSERT文で処理時間に差が
出た可能性が高いと考えられます。

4.ASMLibに関する検証のまとめ
以上でASMLibに関する検証は終了となります。
ASMLibは、作業の効率化と共に、ヒューマンエラーの防止に繋がる、便利なア
ドオン・モジュールです。
また、今回の検証で処理速度に関しても若干ではありますが、ディスクへの
書き込み処理に関連する処理性能の向上も確認できました。
Linux環境でASMを使用する環境であれば、一度お試しいただければと思いま
す。

ドリームジャーニーの快勝がとても嬉しいです。
恵比寿より