連載
» 2012年08月07日 00時00分 UPDATE

知ってトクするシステムコール(7):共有メモリとファイルシステム――その2 (1/2)

mmap(2)で共有メモリを実装する方法はいくつかある。前回、各方法ごとに性能を検証したところ、大きな違いは見られなかった。そこで今回は共有するデータサイズを100MBにして、あらためて性能の違いを調査していく。(編集部)

[後藤大地,@IT]

性能測定、データサイズを大きくしたらどうなる?

 第6回ではmmap(2)を使って共有メモリを実装する方法を紹介した。mmap(2)で共有メモリを実装する場合、いくつかの選択肢があり、それぞれ性能にどういった違いがあるのかを調べた。

 今回は前回の話に引き続き、共有するデータのサイズを変えた場合に性能にどのような違いが発生するのかを調査していく。

 mmap(2)はメモリへのアクセスがそのままファイルへのアクセスになるところにその特徴がある。ファイルをマッピングしなくても利用できるが、本来的にはファイルに対してマッピングを実施するものだ。前回はファイルにマッピングするケースとそうでないケース、ファイルが置かれているファイルシステムをディスク上のUFSかメモリファイルシステムか、などいくつか条件を分けて性能の違いを調査した。

 前回の調査ではほとんど性能の差が見られなかった。これは共有したデータのサイズが2バイトといった極めて小さいサイズだけだったからではないか、と推測した。今回は共有するデータサイズを100MBにして、同様の調査を実施する。

メモリファイルシステムと共有ファイルの作成

 まず、次のように操作して実験環境を作成する。

1. ディスク上のUFS上に100MBの共有ファイルを作成

% dd if=/dev/zero of=/tmp/shm bs=104857600 count=1

2. malloc(9)バックエンドのmdconfigメモリファイルシステムUFS上に100MBの共有ファイルを作成

# mdconfig -a -t malloc -s 200M -u 0
# newfs /dev/md0
# tunefs -n enable /dev/md0
# mkdir /tmp1
# mount -o noatime /dev/md0 /tmp1
# chmod 1777 /tmp1
% dd if=/dev/zero of=/tmp1/shm bs=104857600 count=1

3. スワップバックエンドのmdconfigメモリファイルシステムUFS上に100MBの共有ファイルを作成

# mdconfig -a -t swap -s 200M -u 1
# newfs /dev/md1
# tunefs -n enable /dev/md1
# mkdir /tmp2
# mount -o noatime /dev/md1 /tmp2
# chmod 1777 /tmp2
% dd if=/dev/zero of=/tmp2/shm bs=104857600 count=1

3. tmpfsメモリファイルシステム上に100MBの共有ファイルを作成

# mkdir /tmp3
# mount -t tmpfs tmpfs /tmp3
# chmod 1777 /tmp3
% dd if=/dev/zero of=/tmp3/shm bs=104857600 count=1

 前回紹介した手順とはオプションなどが少々異なっている。これはファイルシステムの条件がより同一に近づくように操作を追加したためだ。ここまで作業すると、共有ファイルを設置するファイルシステムは次のような状態になる。

% df -h | grep tmp
/dev/ada0s1f                          9.7G    101M    8.8G     1%    /tmp
/dev/md0                              193M    100M     77M    56%    /tmp1
/dev/md1                              193M    100M     77M    56%    /tmp2
tmpfs                                  32G    100M     32G     0%    /tmp3
%  
% mount | grep tmp
/dev/ada0s1f on /tmp (ufs, local, noatime, soft-updates)
/dev/md0 on /tmp1 (ufs, local, noatime, soft-updates)
/dev/md1 on /tmp2 (ufs, local, noatime, soft-updates)
tmpfs on /tmp3 (tmpfs, local)
% 

mmap(2)を使った5通りの共有メモリ実装

 前回使ったソースコードを、今回は100MBのデータを読み書きするものへ変更する。一方から100MBのデータを書き込み、もう一方は書き込みが完了したのを検知したら読み出しを開始する。ソースコードはそれぞれ次のとおりとなる。

ipc_mmap+fork.c : ファイルをマッピングしないmmap(2)で共有メモリ

#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
int
main(void)
{
        int i, rp=10;
        long j;
        char *s, *t, b;
        s = mmap(0, 104857600, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
        *s = '0';
        if (0 == fork()) {
                for (i = 0; i < rp; i++) {
                        while ('0' == *s)
                                ;
                        t = s;
                        ++s;
                        for (j = 1; j < 104857600; j++)
                                b = *s++;
                        s = t;
                        *s = '0';
                }
        }
        else {
                for (i = 0; i < rp; i++) {
                        while ('1' == *s)
                                ;
                        t = s;
                        ++s;
                        for (j = 1; j < 104857600; j++)
                                *s++ = 'a';
                        s = t;
                        *s = '1';
                }
        }
}

ipc_mmap+mdconfig_malloc* : mallocバックエンドのmdconfigメモリファイルシステムUFS上のファイルをmmap(2)でマッピングしたケース

#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int
main(void)
{
        int fd, i, rp=10;
        long j;
        char *s, *t;
        fd = open("/tmp1/shm", O_RDWR);
        s = mmap(0, 104857600, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        *s = '0';
        for (i = 0; i < rp; i++) {
                while ('1' == *s)
                        ;
                t = s;
                ++s;
                for (j = 1; j < 104857600; j++)
                        *s++ = 'a';
                s = t;  
                *s = '1';
        }
}
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int
main(void)
{
        int fd, i, rp=10;
        long j;
        char *s, *t, b;
        fd = open("/tmp1/shm", O_RDWR);
        s = mmap(0, 104857600, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        for (i = 0; i < rp; i++) {
                while ('0' == *s)
                        ;
                t = s;
                ++s;
                for (j = 1; j < 104857600; j++)
                        b = *s++;
                s = t;
                *s = '0';
        }
}

ipc_mmap+mdconfig_swap* : スワップバックエンドのmdconfigメモリファイルシステムUFS上のファイルをmmap(2)でマッピングしたケース

#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int
main(void)
{
        int fd, i, rp=10;
        long j;
        char *s, *t;
        fd = open("/tmp2/shm", O_RDWR);
        s = mmap(0, 104857600, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        *s = '0';
        for (i = 0; i < rp; i++) {
                while ('1' == *s)
                        ;
                t = s;
                ++s;
                for (j = 1; j < 104857600; j++)
                        *s++ = 'a';
                s = t;
                *s = '1';
        }
}
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int
main(void)
{
        int fd, i, rp=10;
        long j;
        char *s, *t, b;
        fd = open("/tmp2/shm", O_RDWR);
        s = mmap(0, 104857600, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        for (i = 0; i < rp; i++) {
                while ('0' == *s)
                        ;
                t = s;
                for (j = 1; j < 104857600; j++)
                        b = *s++;
                s = t;
                *s = '0';
        }
}
       1|2 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。