VPOS 의 성능 측정을 위한 문서이다. 현재의 VPOS 에서 성능 측정을 위한 방법과 각종 실험 결과값을 기록하고 있다.
차후에 여기에 기록된 실험 결과값들은 다른 RTOS 와 성능 비교시에 사용될 것이다.

들어가기 전에

예전의 몇몇 성능 결과 값들이 논문에 기록되어 있지만, 구체적으로 어떤 환경에서 어떻게 테스트되었는지 알 수 없기 때문에 현재 내가 사용하고 있는 VPOS 를 기준으로 성능 측정을 했다.
먼저 RTC 를 이용해서 성능 측정을 하려고 했지만, RTC 의 경우 초(sec) 단위만 측정할 수 있기 때문에 사용할 수 없었다.
그래서 타이머(Timer)를 사용하기로 했다. 타이머라면 더 작은 단위의 시간을 측정할 수 있기 때문이다.

알아 두어야 할 것들

s3c2410 에서는 총 5 개(Timer 0 ~ Timer 4) 의 타이머를 지원한다.
현재 VPOS 코드에서의 vh_timer_init() 함수를 보면 아래와 같다.

void vh_timer_init(void)
{
	int timer_load_val;
	int TIMER = 14;
 
	vu_register_dev(0, "Timer", &timer_device_driver_fops, 14); // 디바이스 등록
	vh_interrupt_unmask(TIMER);
	// 설정 시작
 
	vh_rTCFG0 = 0x0f00;    // 0x51000000      ----- 1
	vh_rTCFG1 = 0x0000;	  // 0x51000004      ----- 2
	timer_load_val = 50000000/(2*16*100);    // 15625     ----- 3
	vh_rTCNTB = timer_load_val;              // 0x5100003C      ----- 4
	vh_rTCON = (vh_rTCON & ~0x0700000) | 0x600000;      // 0x51000008 = 0x600000    ----- 5
	vh_rTCON = (vh_rTCON & ~0x0700000) | 0x500000;    // 0x51000008 = 0x500000      ----- 6
 
// 설정 끝
}

유의해서 볼 것은 주석처리를 해놓은 부분이다. 현재 5 개의 타이머 중에서 Timer 4 만을 사용하고 있다. 이 타이머는 특정한 시간이 되면 쓰레드 스케줄링이 일어나도록 인터럽트를 발생시키는 역할을 한다.
s3c2410 유저 메뉴얼(10-1)을 보면, 타이머와 관련한 레지스터들의 설명이 나온다.

번호 설명
1 타이머의 prescaler value 를 설정한다. 여기서는 Timer 4 에 15(0xF) 를 넣는다.
2 타이머의 input 값을 설정한다. 여기서는 Timer 4 에 0000 을 입력하기 때문에 1/2 을 의미한다.
3 계산식의 결과값은 타이머의 초기값을 나타낸다. 타이머는 1 씩 감소하면서 동작하며, 0 이 되었을 경우 인터럽트를 발생시킨다.
4 2 의 결과값은 15625 이다. 이 값을 Timer 4 counter buffer register 에 저장한다.
5 0x51000008 레지스터에서 Timer 4 의 관련한 부분 [[23 ~ 20]]에는 '0110' 이 저장된다.(아래 설명 참조)
6 역시 0x51000008 레지스터에서 Timver 4 의 관련한 부분[[23 ~ 20]]에는 '0101' 이 저장된다.(아래 설명 참조)

시간을 측정하려면, 시간의 단위를 알고 있어야 한다.

1 sec == 1000 ms == 1000000 us == 1000000000 ns == 1000000000000 ps

0x51000008 레지스터를 보면, 위에서 설명한 대로 Timer 4 를 사용한다고 했다. 유저 메뉴얼의 테이블에 나와 있는 용어에 대해서 잠깐 살펴보겠다.

비트 설명
22 0 = One-shot(타이머를 한번만 동작시킴), 1 = Interval mode(auto reload)(타이머가 종료되면 자동으로 초기값을 설정되어 동작함)
21 0 = No operation(아무런 기능이 없음), 1 = Update TCNTB4(TCNTB4 레지스터에 값을 write 한 후에는 반드시 1 로 세팅해주어야 TCNTB4 값이 적용된다.
20 0 = Stop(타이머를 중지시킴), 1 = Start for Timer 4 (타이머를 시작시킴)

유저 메뉴얼(10-11) 을 보면, Timer input clock Frequency 를 구하는 공식이 있다.
현재 s3c2410 은 200 MHz(=FCLK) 으로 동작하고 있으며, 이 중에서 Timer 4 가 사용하는 PCLK 는 50 MHz 으로 동작한다.
이에 대한 설정은 유저 메뉴얼(7-8) 의 표를 보면, HDIVN, PDIVN 값에 따라서 각각 HCLK 와 PCLK 의 값을 정할 수 있도록 나와있다(Divide Ratio)
이를 설정할 수 있는 레지스터는 유저 메뉴얼(7-19) 의 CLKDIVN(0x4C000014) 이다. 이 레지스터의 [[1 ~ 0]] 값을 어떻게 설정하느냐에 따라서 나눠지는 클럭의 비율이 결정된다.
VPOS 에서는 현재 아래와 같이 부트로더 루틴에서 설정하고 있다.

	@ 1:2:4
	mov	r1, #vh_CLK_CTL_BASE         // 0x4c000000
	mov	r2, #vh_vCLKDIVN         // 0x3 (이진수로 11)
	str	r2, [r1, #vh_oCLKDIVN]   // (0x4c000000 + 0x14) = 0x3 을 함으로서 1,1 을 설정한다

그래서 PCLK 의 경우, FCLK 의 1/4 이기 때문에, 50 MHz 이 들어가게 된다.
다시 하던 얘기로 돌아와서, Timer input clock Frequency 공식을 구하면,

50 / {15 + 1} / {2} = 1.5625 MHz

가 된다. 이것을 시간으로 나타내면, 다음과 같다.

(1 / ((50 MHz / 16) / 2) * 0xffff (= 65535) = 0.039 s (= 25.641 Hz)

위의 식에서 0xffff 는 counter buffer 를 65535 로 정의했을 때의 수치다. VPOS 에서는 counter buffer 을 15625 로 설정했기 때문에 식의 값은 약간 바뀌어야 한다.

(1 / ((50 MHz / 16) / 2) * 0x3d09 (= 15625) = 0.00929 s

이 값은 즉, 타이머 인터럽트가 발생하는 시간이다.
그렇다면, 우리가 정작 원하는 counter buffer 의 값이 1 작아졌을 때의 시간은 얼마일까?

0.00929 s / 15625 = 0.00000059510 s (= 0.59510 us)

위와 같다. 이제 우리는 counter buffer 값의 차이를 가지고 시간을 측정할 수 있다.

시간 측정 방법

시간을 측정하기 위해서는 실시간의 타이머 counter 값을 알아야 한다. 우리는 TCNTO4(0x51000040) 레지스터를 읽음으로서, 현재의 타이머 counter 값을 알 수 있다. 앞에서 설정해준대로 이 레지스터의 초기값은 15625 이다. 어떤 루틴의 시작 지점에서 이 레지스터를 읽고, 끝나는 시점에서 레지스터를 읽어서 그 동안의 타이머 counter 값의 차이를 구하면, 실제 걸린 시간을 알 수 있다.

만일 init 라는 함수의 실행 시간을 측정한다면 필요한 위한 루틴은 다음과 같다.

...
test_start = TCNT04;     // test_start 는 전역변수
test_start_tick = current_thread->cpu_tick;         // 타이머 인터럽트 횟수
 
init();     // init 함수가 수행하는데 걸리는 시간을 측정
 
test_end = TCNT04;     // test_end 는 전역변수 
test_end_tick = current_thread->cpu_tick;       // 타이머 인터럽트 횟수
 
printf("start : 0x%x \t %d\n", test_start, test_start_tick);
printf("end : 0x%x \t %d\n", test_end, test_end_tick);
...

실험 종류 및 방법

논문에서 언급한 실험들과 추가적으로 DIVX 를 실행한 상태에서의 실험으로 구성된다.

쓰레드 생성 테스트 : Null 쓰레드 500 개 수행한 시간 측정(pthread_creation 을 호출한 직후 부터 READY 큐에 삽입되는 시점까지)
쓰레드 삭제 테스트 : Null 쓰레드 500 개 종료되는 수행 시간 측정(pthread_exit 를 호출한 직후 부터 할당된 메모리가 해제되는 시점까지)
쓰레드 스위칭 테스트 : 쓰레드의 컨텍스트를 저장하고 복구하는 데 소요되는 시간 측정(500 개의 동일한 우선순의의 Null 쓰레드)
쓰레드 스케줄링 테스트 : READY 큐에서 CPU 를 할당할 쓰레드를 선택하는 데 소요되는 시간 측정(우선순위의 NULL 쓰레드 1 개를 생성하여 1000 번의 스케줄러가 호출된 후 평균시간 측정)
인터럽트 수행 테스트 : 인터럽트 발생 시점 부터 인터럽트 핸들러 진입시점까지의 소요시간을 측정(1000 번의 타이머 인터럽트르 수행하여 측정)
클럭 인터럽트 테스트 : 1000 번의 타이머 인터럽트를 발생시켜 타이머 인터럽트 핸들러의 오버헤드를 측정
DIVX 프로그램 테스트 : 동영상을 처음부터 끝까지 한번 수행시켰을 때의 시간 측정, 각 프레임을 수정했을 때의 시간 측정

실험 결과

do-while 문을 사용해서 500 번 동안의 수행 시간을 측정했다. 총 10 번의 테스트를 통해서 평균 값을 구했다.

쓰레드 생성개수 최소(us) 최대(us) 평균(us) 표준편차
500 1825.1717 2004.8919 1913.60356 270.6931
  • computer/rtcclab/vpos_성능_측정.txt
  • Last modified: 4 years ago
  • by likewind