我们知道可以使用,gprof工具来分析系统性能,但是在linux下面,多线程则不适用,多线程下,只能采集主线程性能数据。.原因是gprof采用ITIMER_PROF信号,在多线程内,只有主线程才能响应该信号。那么采用什么方法,才能够分析所有
线程呢? 关键是能够让各个线程响应ITIMER_PROF信号,下面是通过桩子函数来进行的,就是重写pthread_create函数。
gprof-helper.c
#define _GNU_SOURCE
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <pthread.h>
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;
}
///
然后编译成动态库 gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
使用例子:
/a.c/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void fun1();
void fun2();
void* fun(void * argv);
int main()
{
int i =0;
int id;
pthread_t thread[100];
for(i =0 ;i< 100; i++)
{
id = pthread_create(&thread[i], NULL, fun, NULL);
printf("thread =%d/n",i);
}
printf("dsfsd/n");
return 0;
}
void* fun(void * argv)
{
fun1();
fun2();
return NULL;
}
void fun1()
{
int i = 0;
while(i<100)
{
i++;
printf("fun1/n");
}
}
void fun2()
{
int i = 0;
int b;
while(i<50)
{
i++;
printf("fun2/n");
//b+=i;
}
}
///
gcc -pg a.c gprof-helper.so
运行程序:
./a.out
分析gmon.out:
gprof -b a.out gmon.out
线程呢? 关键是能够让各个线程响应ITIMER_PROF信号,下面是通过桩子函数来进行的,就是重写pthread_create函数。
gprof-helper.c
#define _GNU_SOURCE
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <pthread.h>
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;
}
///
然后编译成动态库 gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
使用例子:
/a.c/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void fun1();
void fun2();
void* fun(void * argv);
int main()
{
int i =0;
int id;
pthread_t thread[100];
for(i =0 ;i< 100; i++)
{
id = pthread_create(&thread[i], NULL, fun, NULL);
printf("thread =%d/n",i);
}
printf("dsfsd/n");
return 0;
}
void* fun(void * argv)
{
fun1();
fun2();
return NULL;
}
void fun1()
{
int i = 0;
while(i<100)
{
i++;
printf("fun1/n");
}
}
void fun2()
{
int i = 0;
int b;
while(i<50)
{
i++;
printf("fun2/n");
//b+=i;
}
}
///
gcc -pg a.c gprof-helper.so
运行程序:
./a.out
分析gmon.out:
gprof -b a.out gmon.out