]> mj.ucw.cz Git - libucw.git/commitdiff
Added a Poor Man's Profiler :-)
authorMartin Mares <mj@ucw.cz>
Sat, 1 Dec 2001 19:19:40 +0000 (19:19 +0000)
committerMartin Mares <mj@ucw.cz>
Sat, 1 Dec 2001 19:19:40 +0000 (19:19 +0000)
lib/Makefile
lib/profile.c [new file with mode: 0644]
lib/profile.h [new file with mode: 0644]

index c353013be0b7055f36d28cec21083f7e0f4b811e..a3ce2aaad1b8e442902e90c3d42224105d7cce8b 100644 (file)
@@ -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 (file)
index 0000000..dea6b93
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *     Sherlock Library -- Poor Man's Profiler
+ *
+ *     (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+#include "lib/lib.h"
+#include "lib/profile.h"
+
+#include <stdio.h>
+
+#ifdef CONFIG_PROFILE_TOD
+#include <sys/time.h>
+
+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 <fcntl.h>
+#include <unistd.h>
+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 (file)
index 0000000..e3e51a2
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *     Sherlock Library -- Poor Man's Profiler
+ *
+ *     (c) 2001 Martin Mares <mj@ucw.cz>
+ */
+
+/*
+ *  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