2006년 11월 2일 목요일

Linux에서 램디스크 잡기

전에 올린 RAMdisk하고는 조금 다른 개념으로 Linux에 RAMdisk를 이용하여 DC의 안정성을 확보하는 어떨까한다.

RAMdisk는 HDD의 Block-device와 동일한 인터패이스를 제공한다. 따라서 별 다른 포팅 없이도 read/write로 입출력을 제어할 수 있다. 가장 큰 장점은 다른 거의 모든 저장 장치에 비해 미칠 듯이 빠르다는 것이다. (랜덤 억세스 단위가 ns) 단점은 휘발성과 가격이겠지만...

각설하고 아래와 같은 테스트 상황을 만들었다.

환경
  • CPU: AMD Athlon(tm) 64 X2 Dual Core Processor 3800+
  • OS: Linux 2.6.18-1.2798.fc6
  • RAM: 2,055,528 KB
  • Compiler: gcc 4.1.1 20061011 (Red Hat 4.1.1-30)
소스
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

uint64_t
getNow(void)
{
        static struct timeval tv;
        gettimeofday(&tv, NULL);
        return (uint64_t)tv.tv_sec*1000000ULL + (uint64_t)tv.tv_usec;
}

int
main(int argc,char* argv[])
{
        const char* proc = basename(argv[0]);
        char name[1024];
        sprintf(name, ".%s.swp", proc);

        do
        {

                if ( argc<2 )
                {
                        const char* proc = basename(argv[0]);
                        printf("%s [file size, MB]\n", proc);
                        break;
                }

                size_t blocks = atoi(argv[1])*1024;
                size_t file_size = 1024*blocks;
                if (file_size<=0)
                {
                        printf("too small size, %s\n", argv[1]);
                        break;
                }

                int fd;
                fd = creat(name, O_RDWR|O_CREAT|O_TRUNC);
                if ( -1 == fd )
                {
                        printf("failed to create file, %s\n", name);
                        break;
                }

                uint64_t sp;
                uint64_t ts_alloc, ts_read, ts_rread;
                printf("file allocating...\n");
                sp = getNow();
                volatile char buf[1024];
                size_t i;

                for (i = 0; i < blocks; i++)
                {
                        if ( -1 == write(fd, (void*)buf, sizeof(buf)) )
                        {
                                printf("failed to allocate file, %s\n", name);
                                unlink(name);
                                break;
                        }
                }

                ts_alloc = getNow() - sp;

                printf("reading...\n");
                lseek(fd, 0, SEEK_SET);
                sp = getNow();
                for (i = 0; i < blocks; i++)
                {
                        read(fd, (void*)buf, sizeof(buf));
                }

                ts_read = getNow() - sp;

                printf("random reading...\n");
                off_t off;
                ts_rread = 0;
                for (i = 0; i < 100000; i++)
                {
                        off = rand()%blocks;
                        off*= 1024;
                        sp = getNow();
                        lseek(fd, off, SEEK_SET);
                        read(fd, (void*)buf, sizeof(buf));
                        ts_rread += getNow() - sp;
                        if (!(i%1000)) printf("%0.2f%%\r", i*100/100000);
                }

                unlink(name);

                printf("file path: %s\n", name);
                printf("file size: %u MB\n", blocks/1024);
                printf("allocation time: %f us/byte\n", (double)ts_alloc/file_size);
                printf("linear read time: %f us/byte\n", (double)ts_read/file_size);
                printf("random read time: %f us/byte\n", (double)ts_rread/100000/sizeof(buf));

                return 0;
        } while (0);

        unlink(name);
        return -1;
}

램디스크 연결
커널 옵션에 ramdisk_size=1024000 추가하고 리부팅
$ cd /tmp
$ mkdir rdsk
$ mkfs -t ext2 /dev/ram0
$ mount /dev/ram0 rdsk

컴파일
$ gcc -o rwtest -O3 rwtest.c

결과(단위: us)
  1. RAMdisk
    • 쓰기: 0.003986
    • 선형 읽기: 0.000295
    • 무작위 읽기: 0.002412
  2. HDD
    • 쓰기: 0.004392
    • 선형 읽기:  0.000325
    • 무작위 읽기:  0.002678

ㅡ_-)a 뭔가 잘못 쟀나?