/* Bash (wallclock-time) profiler. Written by Clifford Wolf.
|
|
*
|
|
* Usage:
|
|
* gcc -shared -fPIC -Wall -o bash_profiler.so bash_profiler.c
|
|
* enable -f ./bash_profiler.so bprof
|
|
*
|
|
* bprof a start; idle_in_a; brof a stop
|
|
* bprof b start; idle_in_b; brof b stop
|
|
* bprof a start; idle_in_a; brof a stop
|
|
*
|
|
* bprof all print
|
|
* enable -d bprof
|
|
*/
|
|
|
|
|
|
/* Some declarations copied from bash-2.05b headers */
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef struct word_desc {
|
|
char *word;
|
|
int flags;
|
|
} WORD_DESC;
|
|
|
|
typedef struct word_list {
|
|
struct word_list *next;
|
|
WORD_DESC *word;
|
|
} WORD_LIST;
|
|
|
|
typedef int sh_builtin_func_t(WORD_LIST *);
|
|
|
|
#define BUILTIN_ENABLED 0x1
|
|
|
|
struct builtin {
|
|
char *name;
|
|
sh_builtin_func_t *function;
|
|
int flags;
|
|
char * const *long_doc;
|
|
const char *short_doc;
|
|
char *handle;
|
|
};
|
|
|
|
|
|
/* my hellobash builtin */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
|
|
long long mytime()
|
|
{
|
|
struct timeval tv;
|
|
gettimeofday(&tv, 0);
|
|
return tv.tv_sec*1000 + tv.tv_usec/1000;
|
|
}
|
|
|
|
struct bprofent;
|
|
|
|
struct bprofent {
|
|
char *id;
|
|
int count;
|
|
long long tv_sum, tv_start;
|
|
struct bprofent *next;
|
|
};
|
|
|
|
struct bprofent *bprofent_list = 0;
|
|
|
|
int bprof_builtin(WORD_LIST *list)
|
|
{
|
|
struct bprofent *this = bprofent_list;
|
|
char *mode, *name;
|
|
|
|
if ( !list || !list->next ) {
|
|
fprintf(stderr, "Usage: bprof {id|all} {start|stop|print}\n");
|
|
return 1;
|
|
}
|
|
|
|
name = list->word->word;
|
|
mode = list->next->word->word;
|
|
|
|
if ( !strcmp(mode, "print") && !strcmp(name, "all") ) {
|
|
while ( this ) {
|
|
printf("%7d %7Ld %10.3f %s\n", this->count, this->tv_sum,
|
|
(float)this->tv_sum/this->count, this->id);
|
|
this = this->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
while ( this ) {
|
|
if ( !strcmp(this->id, name) ) break;
|
|
this = this->next;
|
|
}
|
|
|
|
if ( !this ) {
|
|
this = calloc(1, sizeof(struct bprofent));
|
|
this->id = strdup(name);
|
|
this->next = bprofent_list;
|
|
bprofent_list = this;
|
|
}
|
|
|
|
if ( !strcmp(mode, "start") ) {
|
|
this->tv_start = mytime();
|
|
} else if ( !strcmp(mode, "stop") ) {
|
|
this->tv_sum += mytime() - this->tv_start;
|
|
this->count++;
|
|
} else if ( !strcmp(mode, "print") ) {
|
|
printf("%7d %7Ld %10.3f %s\n", this->count, this->tv_sum,
|
|
(float)this->tv_sum/this->count, this->id);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *bprof_doc[] = {
|
|
"bash profiler",
|
|
0
|
|
};
|
|
|
|
struct builtin bprof_struct = {
|
|
"bprof",
|
|
&bprof_builtin,
|
|
BUILTIN_ENABLED,
|
|
bprof_doc,
|
|
"bash profiler",
|
|
0
|
|
};
|
|
|