FREEDOM. FRIENDS. FEATURES. FIRST. 페도라 한국 사용자 모임

Thread program에 대해 gprof의 사용법

게시판 Tech/Tip Thread program에 대해 gprof의 사용법

  • This topic has 2개 답변, 2명 참여, and was last updated 15 years, 8 months 전에 by
    인베인. This post has been viewed 642 times
  • #12081
    인베인
    참가자
      게시글147 댓글411 총합558
    @leemgs
     

    gcc의 -pg 옵션을 사용하여 컴파일하면 gprof를 통해 함수별 실행 시간을 자세히 살펴 볼수 있다. 방법은 다음과 같이 간단하다.

    $ gcc -pg -o hello hello.c
    $ hello
    $ gprof hello gmon.out

    주의할 점은 컴파일과 링크 옵션 모두에 -pg 가 들어가야만 한다.

    그런데, 리눅스에서 pthread로 사용하여 작성한 프로그램을 gprof 보면 시간 측정이 제대로 되지 않는다. 이럴때엔 아래의 wrapping 함수를 사용하면 제대로된 결과를 얻을수 있다. 사용법은 소스의 주석을 살펴보라.

    물론, 실행 프로그램을 -static 옵션을 사용하여 정적 링크를 했을 경우엔 효과가 없을 것이다.

                               
                   

       

       /* gprof-helper.c -- preload library to profile pthread-enabled programs
       *
       * Authors: Sam Hocevar
       *          Daniel J?nsson
       *
       *  This program is free software; you can redistribute it and/or
       *  modify it under the terms of the Do What The Fuck You Want To
       *  Public License as published by Banlu Kemiyatorn. See
       *  http://sam.zoy.org/projects/COPYING.WTFPL for more details.
       *
       * Compilation example:
       * gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
       *
       * Usage example:
       * LD_PRELOAD=./gprof-helper.so your_program
       */

       #define _GNU_SOURCE
       #include
       #include
       #include
       #include
       #include

       static void * wrapper_routine(void *);

       /* Original pthread function */
       static int (*pthread_create_orig)(pthread_t *__restrict,
                                        __const pthread_attr_t *__restrict,
                                        void *(*)(void *),
                                        void *__restrict) = NULL;

       /* Library initialization function */
       void wooinit(void) __attribute__((constructor));

       void wooinit(void)
       {
          pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create");
          fprintf(stderr, "pthreads: using profiling hooks for gprof\n");
          if(pthread_create_orig == NULL)
          {
              char *error = dlerror();
              if(error == NULL)
              {
                  error = "pthread_create is NULL";
              }
              fprintf(stderr, "%s\n", error);
              exit(EXIT_FAILURE);
          }
       }

       /* Our data structure passed to the wrapper */
       typedef struct wrapper_s
       {
          void * (*start_routine)(void *);
          void * arg;

          pthread_mutex_t lock;
          pthread_cond_t  wait;

          struct itimerval itimer;

       } wrapper_t;

       /* The wrapper function in charge for setting the itimer value */
       static void * wrapper_routine(void * data)
       {
          /* Put user data in thread-local variables */
          void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine;
          void * arg = ((wrapper_t*)data)->arg;

          /* Set the profile timer value */
          setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);

          /* Tell the calling thread that we don't need its data anymore */
          pthread_mutex_lock(&((wrapper_t*)data)->lock);
          pthread_cond_signal(&((wrapper_t*)data)->wait);
          pthread_mutex_unlock(&((wrapper_t*)data)->lock);

          /* Call the real function */
          return start_routine(arg);
       }

       /* Our wrapper function for the real pthread_create() */
       int pthread_create(pthread_t *__restrict thread,
                         __const pthread_attr_t *__restrict attr,
                         void * (*start_routine)(void *),
                         void *__restrict arg)
       {
          wrapper_t wrapper_data;
          int i_return;

          /* Initialize the wrapper structure */
          wrapper_data.start_routine = start_routine;
          wrapper_data.arg = arg;
          getitimer(ITIMER_PROF, &wrapper_data.itimer);
          pthread_cond_init(&wrapper_data.wait, NULL);
          pthread_mutex_init(&wrapper_data.lock, NULL);
          pthread_mutex_lock(&wrapper_data.lock);

          /* The real pthread_create call */
          i_return = pthread_create_orig(thread,
                                         attr,
                                         &wrapper_routine,
                                         &wrapper_data);

          /* If the thread was successfully spawned, wait for the data
           * to be released */

       

          if(i_return == 0)
          {
              pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
          }

          pthread_mutex_unlock(&wrapper_data.lock);
          pthread_mutex_destroy(&wrapper_data.lock);
          pthread_cond_destroy(&wrapper_data.wait);

          return i_return;
       }

    end of line.

    * 오픈소스는 Open Innovationa & 윈윈전략을 도모할 지언정 절대 공짜(무료)임을 뜻하지 않는다.치

1 답변 글타래를 보이고 있습니다
    • #12661
      ELem
      참가자
        게시글74 댓글709 총합783
      @Bardisch
       

      pg옵션은 모르고있던 녀석이네요 ㅎㅎ
      좋은거 알아갑니다 ^^

       
    • #12662
      인베인
      참가자
        게시글147 댓글411 총합558
      @leemgs
       

      최근에 이 -pg ( 프로파일링 옵션)  기능을 이용하여 커널소스의 펑션 트레이싱을 할수 있도록 ftrace  피쳐가 바닐라 커널에도 들어왔읍니다.

       

      * 오픈소스는 Open Innovationa & 윈윈전략을 도모할 지언정 절대 공짜(무료)임을 뜻하지 않는다.치

       
1 답변 글타래를 보이고 있습니다
  • 답변은 로그인 후 가능합니다.

지금 이 순간


안녕하세요. 가입인사드립니다.
페도라 34 출시 일정 - 4월 27일(UTC 14:00)) - 국내 23시경
vmware, virtualbox(버추얼박스) 하드 추가하기
페도라13 x86_64를 다운 받을 수 없을까요?
버츄얼 박스 -> 페도라16 라이브
대구정부통합전산센터 오픈소스DBMS로 지각변동
Havij를 이용한 인젝션 공격을 어떻게 막아야 할까요?
페도라 14 무선랜 잡는 방법좀요!
파티션매직같은 리눅스용 파티션 관리툴(parted)
CPU Frequency Scaling(클럭) 조절하기