From: Martin Mares Date: Sat, 1 Dec 2001 19:19:40 +0000 (+0000) Subject: Added a Poor Man's Profiler :-) X-Git-Tag: holmes-import~1462 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=fb391b2b22680fc3e18bfb5fecdb3c56ae3b6d2a;p=libucw.git Added a Poor Man's Profiler :-) --- diff --git a/lib/Makefile b/lib/Makefile index c353013b..a3ce2aaa 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -7,7 +7,7 @@ SHLIB_OBJS=alloc.o alloc_str.o ctmatch.o db.o fastbuf.o fb-file.o fb-mem.o lists log.o log2.o md5.o md5hex.o mmap.o pagecache.o patimatch.o patmatch.o pool.o \ prime.o random.o realloc.o regex.o timer.o url.o wildmatch.o \ wordsplit.o str_ctype.o str_upper.o bucket.o conf.o object.o sorter.o \ - finger.o proctitle.o ipaccess.o + finger.o proctitle.o ipaccess.o profile.o obj/lib/libsh.a: $(addprefix obj/lib/,$(SHLIB_OBJS)) diff --git a/lib/profile.c b/lib/profile.c new file mode 100644 index 00000000..dea6b932 --- /dev/null +++ b/lib/profile.c @@ -0,0 +1,118 @@ +/* + * Sherlock Library -- Poor Man's Profiler + * + * (c) 2001 Martin Mares + */ + +#include "lib/lib.h" +#include "lib/profile.h" + +#include + +#ifdef CONFIG_PROFILE_TOD +#include + +void +prof_init(prof_t *c) +{ + c->sec = c->usec = 0; +} + +void +prof_switch(prof_t *o, prof_t *n) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + if (n) + { + n->start_sec = tv.tv_sec; + n->start_usec = tv.tv_usec; + } + if (o) + { + o->sec += tv.tv_sec - o->start_sec; + o->usec += tv.tv_usec - o->start_usec; + if (o->usec < 0) + { + o->usec += 1000000; + o->sec++; + } + else while (o->usec >= 1000000) + { + o->usec -= 1000000; + o->sec--; + } + } +} + +int +prof_format(char *buf, prof_t *c) +{ + return sprintf(buf, "%d.%06d", c->sec, c->usec); +} +#endif + +#ifdef CONFIG_PROFILE_TSC +void +prof_init(prof_t *c) +{ + c->ticks = 0; +} + +int +prof_format(char *buf, prof_t *c) +{ + return sprintf(buf, "%Ld", c->ticks); +} +#endif + +#ifdef CONFIG_PROFILE_KTSC +#include +#include +static int self_prof_fd = -1; + +void +prof_init(prof_t *c) +{ + if (self_prof_fd < 0) + { + self_prof_fd = open("/proc/self/profile", O_RDONLY, 0); + if (self_prof_fd < 0) + die("Unable to open /proc/self/profile: %m"); + } + c->ticks_user = 0; + c->ticks_sys = 0; +} + +void +prof_switch(prof_t *o, prof_t *n) +{ + u64 u, s; + byte buf[256]; + + int l = pread(self_prof_fd, buf, sizeof(buf)-1, 0); + ASSERT(l > 0 && l < (int)sizeof(buf)-1); + buf[l] = 0; + l = sscanf(buf, "%Ld%Ld", &u, &s); + ASSERT(l == 2); + + if (n) + { + n->start_user = u; + n->start_sys = s; + } + if (o) + { + u -= o->start_user; + o->ticks_user += u; + s -= o->start_sys; + o->ticks_sys += s; + } +} + +int +prof_format(char *buf, prof_t *c) +{ + return sprintf(buf, "%Ld+%Ld", c->ticks_user, c->ticks_sys); +} +#endif diff --git a/lib/profile.h b/lib/profile.h new file mode 100644 index 00000000..e3e51a28 --- /dev/null +++ b/lib/profile.h @@ -0,0 +1,101 @@ +/* + * Sherlock Library -- Poor Man's Profiler + * + * (c) 2001 Martin Mares + */ + +/* + * Usage: + * prof_t cnt; + * prof_init(&cnt); + * ... + * prof_start(&cnt); + * ... + * prof_stop(&cnt); + * printf("%s\n", PROF_STRING(&cnt)); + */ + +/* Profiling method to use */ +#define CONFIG_PROFILE_TOD /* gettimeofday() */ +#undef CONFIG_PROFILE_TSC /* i386 TSC */ +#undef CONFIG_PROFILE_KTSC /* kernel TSC profiler */ + +#ifdef CONFIG_PROFILE_TOD +#define CONFIG_PROFILE +#define PROF_STR_SIZE 21 + +typedef struct { + u32 start_sec, start_usec; + s32 sec, usec; +} prof_t; + +#endif + +#ifdef CONFIG_PROFILE_TSC +#define CONFIG_PROFILE +#define CONFIG_PROFILE_INLINE +#define PROF_STR_SIZE 24 + +typedef struct { + u64 start_tsc; + u64 ticks; +} prof_t; + +#define rdtscll(val) __asm__ __volatile__("rdtsc" : "=A" (val)) + +static inline void prof_start(prof_t *c) +{ + rdtscll(c->start_tsc); +} + +static inline void prof_stop(prof_t *c) +{ + u64 tsc; + rdtscll(tsc); + tsc -= c->start_tsc; + c->ticks += tsc; +} + +static inline void prof_switch(prof_t *o, prof_t *n) +{ + u64 tsc; + rdtscll(tsc); + n->start_tsc = tsc; + tsc -= o->start_tsc; + o->ticks += tsc; +} +#endif + +#ifdef CONFIG_PROFILE_KTSC +#define CONFIG_PROFILE +#define PROF_STR_SIZE 50 + +typedef struct { + u64 start_user, start_sys; + u64 ticks_user, ticks_sys; +} prof_t; +#endif + +#ifdef CONFIG_PROFILE + +/* Stuff common for all profilers */ +#ifndef CONFIG_PROFILE_INLINE +void prof_switch(prof_t *, prof_t *); +static inline void prof_start(prof_t *c) { prof_switch(NULL, c); } +static inline void prof_stop(prof_t *c) { prof_switch(c, NULL); } +#endif +int prof_format(char *, prof_t *); +void prof_init(prof_t *); + +#else + +/* Dummy profiler with no output */ +typedef struct { } prof_t; +static inline void prof_init(prof_t *c UNUSED) { } +static inline void prof_start(prof_t *c UNUSED) { } +static inline void prof_stop(prof_t *c UNUSED) { } +static inline void prof_switch(prof_t *c UNUSED, prof_t *d UNUSED) { } +static inline void prof_format(char *b, prof_t *c UNUSED) { strcpy(b, "?"); } +#define PROF_STR_SIZE 2 + +#endif