2006/10/13

유닉스의 각 설비에서 데이터 seek효율성

간단한 데이터 베이스를 만든다고 가정했을 때, 원하는 데이터의 위치를 찾기 위한 seek 과정은 프로그램의 속도성능을 결정짓는 중요한 요소다.

그래서 이에 대한 테스트를 해보기로 했다. 테스트는 유닉스 설비별로 이루어질 것이다.
  1. 메모리
  2. 메모리맵(MM)
  3. 파일
  4. 공유메모리
상식적으로 생각해 봤을 때, 메모리에서 연산하는게 가장 빠르겠지만, 이 경우 많은 메모리를 사용해야 한다는 단점이 있다. 파일 같은 경우는 저장이 용이하고 메모리 사용이 상대적으로 적다는 장점이 있지만 Disk I/O가 문제가 될것이다. 공유메모리의 경우 커널에서 관리하므로 빠르게 사용할 수 있다는 장점이 있을 거 같지만, 커널 메모리를 사용할 경우 다른 자원에 비해서 제약이 크다는 단점이 있을 것이다. 메모리 맵도 마찬가지로 장단점을 가지고 있을 것이다.

결 국 속도 우선인지, 메모리 우선인지 그리고 각 방법을 선택했을 때, 다른 방법을 선택했을 때보다 그만큼의 이익을 얻을 수 있는지에 대한 판단을 해야 하고, 이 문서는 이러한 판단에 근거를 만들기 위한 데이터의 수집을 목적으로 작성되었다.

테스트 시나리오

다음과 같은 고정된 크기를 가지는 구조체를 포함하는 배열을 만든다.
struct data
{
int did;
int score;
};

배열의 크기는 10,000,000개로 9Mbyte 정도의 크기를 가지게 될 것이다. 이렇게 만들어진 데이터를 파일, 메모리, 공유메모리(:12), 메모리맵에 적재하고 seek(2)에 걸리는 시간을 검사한다.

Memory 우선 사용 테스트

malloc(:3)을 이용해서 천만개의 메모리를 할당하고 여기에서 값을 읽어들이는데 걸리는 시간을 테스트 했다. 10000*1, 10000*2, 10000*3,..., 10000*n으로 데이터를 읽어들였다.

#include
#include
#include
#include
#include
#include
#include
#include

struct data
{
int did;
int score;
};

const int dsize = 10000000;

int main(int argc, char **argv)
{
struct data *ldata;
struct data dumy;
int i,j,n;
clock_t stime, etime;
int offset = 10000;
ldata = (struct data *)malloc(sizeof(struct data) * dsize);
memset((void *)ldata, 0x00, sizeof(struct data)*dsize);

n = dsize/offset;
for (i = 0; i < n; i++)
{
stime = clock();
for (j = 0; j < offset * (i+1); j++)
{
dumy = ldata[j];
}
etime = clock();
//printf("%d : %.3fsn", offset * (i+1), (double)(etime-stime)/CLOCKS_PER_SEC);
printf("%d %.3fn", j, (double)(etime-stime)/CLOCKS_PER_SEC);
}
}

다음은 테스트 결과를 gnuplot(:12)를 이용해서 출력한 화면이다.


파일우선 테스트

파일에서 읽을 때 걸리는 시간을 측정해 보았다. 측정방식은 Memory방식과 동일하며, 이를 위해 다음과 같은 프로그램을 만들었다. *8 하는 것만으로 데이터의 위치를 구할 수 있을 것임으로 굳이 seek함수를 이용하진 않았다. 다음은 테스트를 위해 작성한 코드다.

#include
#include
#include
#include
#include
#include
#include
#include

struct data
{
int did;
int score;
};

const int dsize = 10000000;

int main(int argc, char **argv)
{
struct data *ldata;
struct data dumy;
int i,j,n;
clock_t stime, etime;
int offset = 10000;
int fd;


fd = open("data.dmb", O_CREAT|O_RDWR);
if (fd < 0)
{
perror("Open errorn");
}
memset((void *)&dumy, 0x00, sizeof(struct data));
for (i = 0; i < 10000000; i++)
{
write(fd, (void *)&dumy, sizeof(struct data));
}
printf("File Create endn");

n = dsize/offset;
for (i = 0; i < n; i++)
{
stime = clock();
for (j = 0; j < offset * (i+1); j++)
{
read(fd, (void *)&dumy, sizeof(struct data));
}
etime = clock();
printf("%d %.3fn", j, (double)(etime-stime)/CLOCKS_PER_SEC);
}
}

측정결과는 gnuplot를 이용해서 그래프로 만들었다.


비교를 쉽게 하기 위해서 하나의 그래프로 만들어 봤다.


댓글 없음: