기본 콘텐츠로 건너뛰기

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 뭔가 잘못 쟀나?

댓글

이 블로그의 인기 게시물

Bash Array, Map 정리

Bash에서 Array, Map에 대한 정리. (매번 찾기 귀찮) 찾아보진 않았지만, Bash에서 Array든 Map이든 동일하게 Map(C++에서 Unordered Map)으로 동작하는 것 같다. 왜냐하면, Array의 Index가 연속하지 않아도 동작한다. 그저 Key가 0 이상의 정수인 Map이랑 비슷하게 동작한다. 예) 1, 2, 3, 9, 10 Array # 생성 declare -a empty_array declare -a ar=(haha hoho baba "long string haha hoho") # 접근 echo "ar[0]=${ar[0]}" echo "all as array=${ar[@]}" # 큰따옴표 안에서 각 원소를 따로따로 전달한다. echo "all as one=${ar[*]}" # 큰따옴표 안에서 각 원소를 문자열 하나로 합쳐 전달한다. echo "indexes=${!ar[@]}" echo "indexes=${!ar[*]}" echo "length=${#ar[@]}" echo "length=${#ar[*]}" echo "last=${ar[-1]}" echo "last=${ar[@]: -1}" # 콜론 뒤에 빈 칸이 꼭 필요하다. 옛 방식 # 현재 상황 declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]="long string haha hoho") ar[100]=hello # 인덱스를 건너 뛰어도 동작한다. declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]=...

설치한 패키지에서 RPM 추출하기

오래된 패키지를 관리할 저장소가 없어졌고, 기존 패키지로 다른 서버를 세팅해야할 일이 생겼다면 RPM의 리패키지 기능을 이용해보자. $ rpm -e --repackage [PACKAGE_NAME] 위와 같이 리패키지하면, /var/spool/repackage/ 에 생성한 RPM파일이 있다. :-)