2015. 2. 23.

리눅스 함수 - clock_gettime

 리눅스에서 시간을 측정하는 함수로 clock_gettime이 있다. 아래와 같이 사용하면 된다.

#include <time.h>

int clock_gettime(clockid_t clk_id, struct timespec *tp);



위 함수에서 두번째 인자는 아래의 구조체인데 시간값을 저장할 때 쓴다. <time.h>에서 제공 하는듯..

struct timespec{
   time_t  tv_sec; /초
   long    tv_nes; /나노초
}



이때 첫번째 인자는 여러가지 종류를 쓸 수 있고 상황에 따라 알맞은 것을 쓰면 된다.

clock IDmeaning
CLOCK_REALTIMESystem-wide real-time clock. This clock is supported by all implementations and returns the number of seconds and nanoseconds since the Epoch. This clock can be set viaclock_settime but doing so requires appropriate privileges. When the system time is changed, timers that measure relative intervals are not affected but timers for absolute point in times are.
CLOCK_REALTIME_COARSE (Linux-specific)Faster than CLOCK_REALTIME but not as accurate.
CLOCK_MONOTONICRepresents monotonic time since some unspecified starting point. This clock cannot be set.
CLOCK_MONOTONIC_RAW (Linux-specific)Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments.
CLOCK_MONOTONIC_COARSE (Linux-specific)Like CLOCK_MONOTONIC but faster and not as accurate.
CLOCK_PROCESS_CPUTIME_IDHigh-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_IDThread-specific CPU-time clock.

CLOCK_REALTIME : 시스템 전역의 실제 시계(Epoch 시간)이다. 이 clock은 특권을 통해 clock_settime으로 set이 가능하다. 시스템 시간이 변경되었을 때 상대적인 인터벌 측정 타이머는 영향을 안받지만 절대적 시간 타이머는 영향을 받는다고 한다.

CLOCK_REALTIME_COARSE : 위 clock보다 빠르지만 정확하진 않다.

CLOCK_MONOTONIC : 어떠한 특정 시점(보통 부팅부터 시작)부터 흐른 시간을 나타낸다. set이 불가능하다.

CLOCK_MONOTONIC_RAW : 위와 비슷하지만 NTP에 전혀 영향을 받지 않는 raw hardware-based time에 대한 접근이 가능하다.

CLOCK_MONOTONIC_COARSE : MONOTONIC과 비슷하지만 빠르고 부정확하다.

CLOCK_PROCESS_CPUTIME_ID : 프로세스 단위 CPU 사용 시간.

CLOCK_THREAD_CPUTIME_ID : 쓰레드 단위 CPU 사용 시간




  만약 시간이 흐른 것을 측정하려면 CLOCK_MONOTONIC을 추천한다. 왜냐하면 CLOCK_REALTIME과 다르게 선형적으로 증가하는 것을 보장하기 때문이다. NTP deamon에 의해 영향을 받지만 시간조정 후에 앞이나 뒤로 이동하는 CLOCK_REALTIME과는 다르게 CLOCK_MONOTONIC은 jump하지 않고 끌려내려오는(clock drift)에 의해 보상이 되기 때문.

  CLOCK_MONOTONIC_RAW는 짦은 프로그램에는 괜찮지만 긴 주기를 가지고 있는 프로그램에서는 오차가 발생할 수 있다.

  CLOCK_PROCESS_CPU_TIME_ID 는 오직 프로세스에 의해 소비되는 CPU 시간을 측정한다. 만약 커털이 프로세스를 sleep상태로 해놓았다면 waiting하는 시간은 측정하지 않는다. 만약 프로세스가 multiple threads라면 CLOCK_THREAD_CPUTIME_ID가 비슷한 역할을 하긴 하는데 요구가 이쓴 쓰레드에 대해서만 소비한 CPU 시간을 측정한다.





아래는 예제이다. ( gcc -o gettime gettime.c -lrt )
컴파일 할때는 -lrt를 붙여줘야 한다. (라이브러리를 참조해야하나 보다.)


#include <stdio.h> /* for printf */
#include <stdint.h> /* for uint64 definition */
#include <stdlib.h> /* for exit() definition */
#include <time.h> /* for clock_gettime */

#define BILLION 1000000000L

int localpid(void) {
static int a[9] = { 0 };
return a[0];
}

main(int argc, char **argv)
{
uint64_t diff;
struct timespec start, end;
int i;

/* measure monotonic time */
clock_gettime(CLOCK_MONOTONIC, &start); /* mark start time */
sleep(1); /* do stuff */
clock_gettime(CLOCK_MONOTONIC, &end); /* mark the end time */

diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;
printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff);

/* now re-do this and measure CPU time */
/* the time spent sleeping will not count (but there is a bit of overhead */
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); /* mark start time */
sleep(1); /* do stuff */
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); /* mark the end time */

diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;
printf("elapsed process CPU time = %llu nanoseconds\n", (long long unsigned int) diff);

exit(0);
}



 1초간 sleep를 하고 시간을 측정하는 것인데 각 CLOCK마다 다른 결과값이 나온다.
이론적으로는 CLOCK_PROCESS_CPU_TIME_ID은 waiting일 때 시간을 측정하지 않으므로 대체로 더 작은 값이 나와야한다.



출처 :
https://www.cs.rutgers.edu/~pxk/416/notes/c-tutorials/gettime.html

댓글 없음: