- This topic has 2개 답변, 2명 참여, and was last updated 14 years, 2 months 전에 by 인베인. This post has been viewed 447 times
-
-
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
#includestatic 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 & 윈윈전략을 도모할 지언정 절대 공짜(무료)임을 뜻하지 않는다.치
- 답변은 로그인 후 가능합니다.