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

Thread program에 대해 gprof의 사용법

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

  • This topic has 2개 답변, 2명 참여, and was last updated 14 years, 2 months 전에 by
    인베인. This post has been viewed 447 times
  • #12081
    인베인
    참가자
      게시글147 댓글412 총합559
    @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 댓글719 총합793
      @Bardisch
       

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

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

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

       

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

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

지금 이 순간


KDE5의 defaultDownloadPath는 어디에 정의되어 있는지 아시는 분 계신가요?
페도라 11 실행시 반복적인 비프음 발생 오류
vmware, virtualbox(버추얼박스) 하드 추가하기
F36 배경화면 정상적으로 신규 설치 가능
페도라 20 amd 그래픽 드라이버 설치 질문입니다.
apache php cubrid 연동(phpcubadmin 포함)
한글화 번역툴 - poedit
[ffmpeg] 디카 동영상 mov 파일을 mpeg 파일로 변환하기
레드햇 - 올해의 RHCP 에 도전하세요
오늘 가입했습니다!