C의 getrusage 함수로 시스템 시간 측정

Jinku Hu 2023년10월12일
  1. getrusage기능을 사용하여 단일 스레드 프로그램의 시스템 시간 측정
  2. getrusage기능을 사용하여 멀티 스레드 프로그램의 시스템 시간 측정
C의 getrusage 함수로 시스템 시간 측정

이 기사에서는 C에서getrusage기능을 사용하여 시스템 시간을 측정하는 여러 방법을 보여줍니다.

getrusage기능을 사용하여 단일 스레드 프로그램의 시스템 시간 측정

일반적으로 실행중인 프로그램에는 두 가지 시간 구성 요소가 있습니다. 시스템 시간은 프로그램이 커널 모드에서 실행되는 기간과 사용자 시간을 나타내며 사용자 모드에서 경과 한 실행 시간을 나타냅니다. 두 값의 합계를 프로세스 시간이라고하며 이는 프로그램의 성능을 최적화 할 때 유용한 측정입니다.

getrusage함수는 프로세스에 대한 여러 데이터 포인트를 검색하며 그 중 하나는struc timeval오브젝트로 표시되는 시스템 시간입니다. getrusage는 정수 값과struct rusage오브젝트의 주소를 인수로 사용합니다. 정수는 측정해야하는 스레드 / 프로세스를 지정하며 다음 사전 정의 된 매크로 값RUSAGE_SELF,RUSAGE_CHILDREN또는RUSAGE_THREAD를 가질 수 있습니다.

반면rusage구조는 사전에 선언되어야하며 성공적인 함수 호출은 해당 값을 그 안에 저장합니다. timeval구조에는 시간을 나타내는 초와 마이크로 초라는 두 개의 데이터 멤버가 포함되어 있으므로, 경과 시간을 초 단위로 계산하기 위해diffUserTimediffSystemTime함수를 구현했습니다.

#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <unistd.h>

enum { NUM_ITERS = 1000000 };

void loopFunc1(size_t num) {
  int tmp = 0;
  for (int i = 0; i < num; ++i) {
    tmp += 1;
  }
}

void *loopFunc2(size_t num) {
  for (int i = 0; i < num; ++i) {
    getpid();
  }
  return NULL;
}

float diffUserTime(struct rusage *start, struct rusage *end) {
  return (end->ru_utime.tv_sec - start->ru_utime.tv_sec) +
         1e-6 * (end->ru_utime.tv_usec - start->ru_utime.tv_usec);
}

float diffSystemTime(struct rusage *start, struct rusage *end) {
  return (end->ru_stime.tv_sec - start->ru_stime.tv_sec) +
         1e-6 * (end->ru_stime.tv_usec - start->ru_stime.tv_usec);
}

int main() {
  struct rusage start, end;

  getrusage(RUSAGE_SELF, &start);
  loopFunc1(NUM_ITERS);
  getrusage(RUSAGE_SELF, &end);

  printf("loopFunc1 stats:\n");
  printf("  CPU time: %.06f sec user, %.06f sec system\n",
         diffUserTime(&start, &end), diffSystemTime(&start, &end));

  getrusage(RUSAGE_SELF, &start);
  loopFunc1(NUM_ITERS);
  getrusage(RUSAGE_SELF, &end);

  printf("loopFunc2 stats:\n");
  printf("  CPU time: %.06f sec user, %.06f sec system\n",
         diffUserTime(&start, &end), diffSystemTime(&start, &end));

  exit(EXIT_SUCCESS);
}

출력:

loopFunc1 stats:
  CPU time: 0.002193 sec user, 0.000000 sec system
loopFunc2 stats:
  CPU time: 0.002087 sec user, 0.000190 sec system

getrusage기능을 사용하여 멀티 스레드 프로그램의 시스템 시간 측정

getrusage함수는 호출 프로세스의 모든 스레드가 사용하는 시스템 시간을 검색 할 수도 있습니다. RUSAGE_SELF인수는이 기능을 지정하며 이전 예에서 볼 수 있듯이 단일 스레드 프로그램에서 상호 사용할 수 있습니다.

다음 샘플 코드에서는 16 개의 스레드를 생성하고, 모두 동일한loopFunc2함수를 실행하고 종료합니다. 그럼에도 불구하고getrusage호출로 검색된 시간은이를 생성 한 스레드를 포함하여 모든 스레드에서 합산 된 경과 시간과 같습니다. 한편, 사용자가 호출 스레드에서만 소비되는 시스템 시간을 측정하려는 경우RUSAGE_THREAD를 첫 번째 인수로 전달할 수 있습니다. 그러나RUSAGE_THREAD값은 Linux에 따라 다르며_GNU_SOURCE는 헤더 파일 앞에 정의되어야 포함해야합니다.

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <threads.h>
#include <unistd.h>

enum { NUM_ITERS = 1000000, NUM_THREADS = 16 };

void *loopFunc2(size_t num) {
  for (int i = 0; i < num; ++i) {
    getpid();
  }
  return NULL;
}

float diffUserTime(struct rusage *start, struct rusage *end) {
  return (end->ru_utime.tv_sec - start->ru_utime.tv_sec) +
         1e-6 * (end->ru_utime.tv_usec - start->ru_utime.tv_usec);
}

float diffSystemTime(struct rusage *start, struct rusage *end) {
  return (end->ru_stime.tv_sec - start->ru_stime.tv_sec) +
         1e-6 * (end->ru_stime.tv_usec - start->ru_stime.tv_usec);
}

int main() {
  struct rusage start, end;
  thrd_t threads[NUM_THREADS];
  int rc;

  getrusage(RUSAGE_SELF, &start);
  for (int i = 0; i < NUM_THREADS; i++) {
    rc = thrd_create(&threads[i], (thrd_start_t)loopFunc2, (void *)NUM_ITERS);
    if (rc == thrd_error) {
      perror("[ERROR] thrd_create() call failed\n");
    }
  }
  loopFunc2(NUM_ITERS);

  getrusage(RUSAGE_SELF, &end);
  printf("loopFunc2 stats:\n");
  printf("  CPU time: %.06f sec user, %.06f sec system\n",
         diffUserTime(&start, &end), diffSystemTime(&start, &end));

  exit(EXIT_SUCCESS);
}

출력:

loopFunc2 stats:
  CPU time: 0.599556 sec user, 0.233000 sec system
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

관련 문장 - C Time