FEMU에서 프로젝트 중 warm up process 구현

kyungminLim·2024년 7월 2일
0

trace replay 중 write된 적없는 위치의 Data를 읽어오는 fail을 덜어내기 위한 code

RocksDB YCSB trace data를 trace replay 프로그램을 사용해서 Trace replay를 실행하였다.
YCSB trace-16번 데이터를 i/o를 내리던 중, write된 적없는 위치를 read하는 현상이 발생하는 것을 확인하고 해당 fail이 일어나는 것을 방지하기 위해 read flag에 해당하는 data를 따로 추출하여 해당 data를 test를 위한 i/o를 수행전 미리 write시킴으로(여기서는 이것을 warm up이라고 하기로 했다.) fail을 방지한다.

여기서는 Asynchronous I/O를 사용하여 disk i/o를 실행하였다.

초기화 및 file & disk open

char warm_up_line[200];
FILE *warm_up_file = fopen("./warm_up_trace.dat", "r");	// 뽑아놓은 read flag data

if(warm_up_file == NULL){
	fprintf(stderr, "Failed to open warm up trace file\n");
    exit(1);
}

int warm_up_fd = open("/dev/nvme0n1", O_WRONLY | O_DIRECT);
if(warm_up_fd < 0){
	perror("Failed to open device file\n");
    exit(1);
}

long long sectornum;
int sectorsize;
int lpn, size;

void *warm_buf;
  • file open : 'warm_up_trace.dat' file을 read mode로 열고, '/dev/nvme0n1' 를 WRONLY | DIRECT I/O 모드로 연다.

비동기 I/O 설정

struct iocb *iocbs[128];		// 비동기 I/O 요청 배열
struct io_event events[128];	// 완료된 I/O 이벤트 배열
int iocb_count = 0, count = 0;
io_context_t ctx;
memset(&ctx, 0, sizeof(ctx));

if(io_setup(128, &ctx) != 0){ 	// 비동기 I/O context 초기화
	perror("io_setup");
    exit(1);
}
  • 비동기 I/O 설정 : I/O 제어 블록 배열과 이벤트 배열을 선언하고, 비동기 I/O context를 초기화한다.

warming up routine

while(fgets(warm_up_line, sizeof(warm_up_line), warm_up_file) != NULL){
	if(sscanf(warm_up_line, "%d\t%d", &lpn, &size) == 2){
    	sectornum = lpn * PAGE_SIZE / SECTOR_SIZE;
        sectorsize = size / SECTOR_SIZE;
        
        warm_align_sector(&sectornum, &sectorsize);
		long long offset = sectornum * SECTOR_SIZE;
        size_t bytes = sectorsize * SECTOR_SIZE;
        
        void *warm_buf = allocate_aligned_buffer(bytes);	// 정렬된 buffer 할당
        if(warm_buf == NULL){
        	perror("Failed to allocate warm buffer\n");
            close(warm_up_fd);
            fclose(warm_up_file);
            exit(1);
        }
        
        struct iocb *iocb = malloc(sizeof(struct iocb));	// I/O 제어 블록 할당
        io_prep_pwrite(iocb, warm_up_df, warm_buf, bytes, offset);	// 비동기 쓰기 준비
        iocbs[iocb_count++] = iocb;
        
        if(iocb_count == 128){
        	int ret = io_submit(ctx, iocb_count, iocbs);	// 비동기 I/O submit
            if(ret < 0){
            	perror("io_submit");
                exit(1);
            }
            
            int events_count = io_getevents(ctx, iocb_count, iocb_count, events, NULL);	// 완료된 I/O event 가져오기
            if(events_count < 0){
            	perror("io_getevents");
                exit(1);
            }
            
            for(int i = 0; i < events_count; i++){
            	free((void *)events[i].obj);	// 완료된 I/O 제어 블록 해제
                free((void *)events[i].data);	// 완료된 데이터 버퍼 해제
            }
            
            iocb_count = 0;		// I/O 제어 블록 카운트 초기화
        }
        
		free(warm_buf);
    }
}

0개의 댓글