/* 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 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 #include #include #include 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 };