[RFC] filter profiling

Lennert Buytenhek buytenh at wantstofly.org
Tue Aug 29 11:55:29 CEST 2017


On Tue, Aug 29, 2017 at 12:05:26PM +0300, Lennert Buytenhek wrote:

> (Right now, my patch only prints the top 'stack frame' when receiving
> SIGUSR2, but there's no reason you wouldn't be able to instrument
> interpret() to thread the stack 'frames', so that you'd be able to get
> a full config language stack trace when a profiling event is triggered.)

Something like this (on top of the previous patch).  This is complicated
slightly by how bird builds its parse tree and that it uses tail recursion
in interpret() to jump to the next statement.


diff --git a/filter/filter.c b/filter/filter.c
index d58c6cb4..e0e4bc56 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -1517,62 +1517,84 @@ __interpret(struct f_inst *what)
     bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
   }
   if (what->next)
-    return interpret(what->next);
+    return __interpret(what->next);
   return res;
 }
 
+struct frame
+{
+  struct frame *parent;
+  struct f_inst *inst;
+};
+
 #define barrier() __asm__ __volatile__("": : :"memory")
 
-static char *file_name;
-static int lino;
+static struct frame *frame;
 
 static struct f_val
 interpret(struct f_inst *what)
 {
+  struct frame f;
   struct f_val ret;
 
   if (what != NULL) {
-    lino = what->lineno;
+    f.parent = frame;
+    f.inst = what;
     barrier();
-    file_name = what->file_name;
+    frame = &f;
   }
 
   ret = __interpret(what);
 
   if (what != NULL) {
-    file_name = NULL;
+    frame = f.parent;
     barrier();
-    lino = -1;
   }
 
   return ret;
 }
 
+static void dump_frame(struct frame *f)
+{
+  char buf[1024];
+
+  if (f->parent != NULL)
+    dump_frame(f->parent);
+
+  snprintf(buf, sizeof(buf), "%s%s:%d\n",
+	   (f->parent != NULL) ? "  " : "",
+	   f->inst->file_name, f->inst->lineno);
+
+  write(2, buf, strlen(buf));
+}
+
 static void handle_sigusr2(int sig UNUSED)
 {
   char prefix[64];
-  char buf[1024];
 
-  if (file_name == NULL) {
+  if (frame == NULL) {
 //    write(2, "not interpreting an f_inst right now\n", 37);
     return;
   }
 
+  write(2, "===\n", 4);
+
   prefix[0] = 0;
 #ifndef IPV6
   if (f_rte != NULL) {
     struct fib_node *n = &(*f_rte)->net->n;
     ip_addr addr = n->prefix;
 
-    snprintf(prefix, sizeof(prefix), "%d.%d.%d.%d/%d",
+    snprintf(prefix, sizeof(prefix), "%d.%d.%d.%d/%d\n",
 	     (addr >> 24) & 0xff, (addr >> 16) & 0xff,
 	     (addr >> 8) & 0xff, addr & 0xff, n->pxlen);
   }
 #endif
+  write(2, prefix, strlen(prefix));
 
-  snprintf(buf, sizeof(buf), "%s:%d %s\n", file_name, lino, prefix);
+  dump_frame(frame);
 
-  write(2, buf, strlen(buf));
+  write(2, "===\n", 4);
 }
 
 void filter_profile_init(void)


More information about the Bird-users mailing list