perf callchain: Use cached rbtrees
authorDavidlohr Bueso <dave@stgolabs.net>
Thu, 6 Dec 2018 19:18:15 +0000 (11:18 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 25 Jan 2019 14:12:09 +0000 (15:12 +0100)
At the cost of an extra pointer, we can avoid the O(logN) cost of
finding the first element in the tree (smallest node), which is
something required for nearly every in/srcline callchain node deletion
(in/srcline__tree_delete()).

Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/20181206191819.30182-4-dave@stgolabs.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/srcline.c
tools/perf/util/srcline.h

index cbe6e7d..9ec4b2e 100644 (file)
@@ -1199,8 +1199,8 @@ struct dso *dso__new(const char *name)
                dso__set_short_name(dso, dso->name, false);
                dso->symbols = dso->symbol_names = RB_ROOT;
                dso->data.cache = RB_ROOT;
-               dso->inlined_nodes = RB_ROOT;
-               dso->srclines = RB_ROOT;
+               dso->inlined_nodes = RB_ROOT_CACHED;
+               dso->srclines = RB_ROOT_CACHED;
                dso->data.fd = -1;
                dso->data.status = DSO_DATA_STATUS_UNKNOWN;
                dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
index 2de54c0..40edfb3 100644 (file)
@@ -143,8 +143,8 @@ struct dso {
        struct rb_root   *root;         /* root of rbtree that rb_node is in */
        struct rb_root   symbols;
        struct rb_root   symbol_names;
-       struct rb_root   inlined_nodes;
-       struct rb_root   srclines;
+       struct rb_root_cached inlined_nodes;
+       struct rb_root_cached srclines;
        struct {
                u64             addr;
                struct symbol   *symbol;
index dc86597..00f2155 100644 (file)
@@ -594,11 +594,12 @@ struct srcline_node {
        struct rb_node          rb_node;
 };
 
-void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline)
+void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline)
 {
-       struct rb_node **p = &tree->rb_node;
+       struct rb_node **p = &tree->rb_root.rb_node;
        struct rb_node *parent = NULL;
        struct srcline_node *i, *node;
+       bool leftmost = true;
 
        node = zalloc(sizeof(struct srcline_node));
        if (!node) {
@@ -614,16 +615,18 @@ void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline)
                i = rb_entry(parent, struct srcline_node, rb_node);
                if (addr < i->addr)
                        p = &(*p)->rb_left;
-               else
+               else {
                        p = &(*p)->rb_right;
+                       leftmost = false;
+               }
        }
        rb_link_node(&node->rb_node, parent, p);
-       rb_insert_color(&node->rb_node, tree);
+       rb_insert_color_cached(&node->rb_node, tree, leftmost);
 }
 
-char *srcline__tree_find(struct rb_root *tree, u64 addr)
+char *srcline__tree_find(struct rb_root_cached *tree, u64 addr)
 {
-       struct rb_node *n = tree->rb_node;
+       struct rb_node *n = tree->rb_root.rb_node;
 
        while (n) {
                struct srcline_node *i = rb_entry(n, struct srcline_node,
@@ -640,15 +643,15 @@ char *srcline__tree_find(struct rb_root *tree, u64 addr)
        return NULL;
 }
 
-void srcline__tree_delete(struct rb_root *tree)
+void srcline__tree_delete(struct rb_root_cached *tree)
 {
        struct srcline_node *pos;
-       struct rb_node *next = rb_first(tree);
+       struct rb_node *next = rb_first_cached(tree);
 
        while (next) {
                pos = rb_entry(next, struct srcline_node, rb_node);
                next = rb_next(&pos->rb_node);
-               rb_erase(&pos->rb_node, tree);
+               rb_erase_cached(&pos->rb_node, tree);
                free_srcline(pos->srcline);
                zfree(&pos);
        }
@@ -682,28 +685,32 @@ void inline_node__delete(struct inline_node *node)
        free(node);
 }
 
-void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines)
+void inlines__tree_insert(struct rb_root_cached *tree,
+                         struct inline_node *inlines)
 {
-       struct rb_node **p = &tree->rb_node;
+       struct rb_node **p = &tree->rb_root.rb_node;
        struct rb_node *parent = NULL;
        const u64 addr = inlines->addr;
        struct inline_node *i;
+       bool leftmost = true;
 
        while (*p != NULL) {
                parent = *p;
                i = rb_entry(parent, struct inline_node, rb_node);
                if (addr < i->addr)
                        p = &(*p)->rb_left;
-               else
+               else {
                        p = &(*p)->rb_right;
+                       leftmost = false;
+               }
        }
        rb_link_node(&inlines->rb_node, parent, p);
-       rb_insert_color(&inlines->rb_node, tree);
+       rb_insert_color_cached(&inlines->rb_node, tree, leftmost);
 }
 
-struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr)
+struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr)
 {
-       struct rb_node *n = tree->rb_node;
+       struct rb_node *n = tree->rb_root.rb_node;
 
        while (n) {
                struct inline_node *i = rb_entry(n, struct inline_node,
@@ -720,15 +727,15 @@ struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr)
        return NULL;
 }
 
-void inlines__tree_delete(struct rb_root *tree)
+void inlines__tree_delete(struct rb_root_cached *tree)
 {
        struct inline_node *pos;
-       struct rb_node *next = rb_first(tree);
+       struct rb_node *next = rb_first_cached(tree);
 
        while (next) {
                pos = rb_entry(next, struct inline_node, rb_node);
                next = rb_next(&pos->rb_node);
-               rb_erase(&pos->rb_node, tree);
+               rb_erase_cached(&pos->rb_node, tree);
                inline_node__delete(pos);
        }
 }
index 5762212..b11a0aa 100644 (file)
@@ -19,11 +19,11 @@ void free_srcline(char *srcline);
 char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line);
 
 /* insert the srcline into the DSO, which will take ownership */
-void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline);
+void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline);
 /* find previously inserted srcline */
-char *srcline__tree_find(struct rb_root *tree, u64 addr);
+char *srcline__tree_find(struct rb_root_cached *tree, u64 addr);
 /* delete all srclines within the tree */
-void srcline__tree_delete(struct rb_root *tree);
+void srcline__tree_delete(struct rb_root_cached *tree);
 
 #define SRCLINE_UNKNOWN  ((char *) "??:0")
 
@@ -46,10 +46,11 @@ struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
 void inline_node__delete(struct inline_node *node);
 
 /* insert the inline node list into the DSO, which will take ownership */
-void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines);
+void inlines__tree_insert(struct rb_root_cached *tree,
+                         struct inline_node *inlines);
 /* find previously inserted inline node list */
-struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr);
+struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr);
 /* delete all nodes within the tree of inline_node s */
-void inlines__tree_delete(struct rb_root *tree);
+void inlines__tree_delete(struct rb_root_cached *tree);
 
 #endif /* PERF_SRCLINE_H */