perf util: Use cached rbtree for rblists
authorDavidlohr Bueso <dave@stgolabs.net>
Thu, 6 Dec 2018 19:18:16 +0000 (11:18 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 25 Jan 2019 14:12:10 +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 any of the strlist or intlist traversals
(XXX_for_each_entry()). There are a number of users in perf of these
(particularly strlists), including probes, and buildid.

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-5-dave@stgolabs.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/intlist.h
tools/perf/util/metricgroup.c
tools/perf/util/rb_resort.h
tools/perf/util/rblist.c
tools/perf/util/rblist.h
tools/perf/util/stat-shadow.c
tools/perf/util/strlist.h

index 85bab8735fa9b9e0d4fc35a65752de175a99c243..5c19ee001299352028ad4469b71b06925f1bc441 100644 (file)
@@ -45,7 +45,7 @@ static inline unsigned int intlist__nr_entries(const struct intlist *ilist)
 /* For intlist iteration */
 static inline struct int_node *intlist__first(struct intlist *ilist)
 {
-       struct rb_node *rn = rb_first(&ilist->rblist.entries);
+       struct rb_node *rn = rb_first_cached(&ilist->rblist.entries);
        return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
 }
 static inline struct int_node *intlist__next(struct int_node *in)
index a28f9b5cc4ffed9c2a4a1a131e2d258b693284da..8529cbd3955b8a513f8b87221ba4570f1181f27f 100644 (file)
@@ -352,7 +352,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
        else if (metrics && !raw)
                printf("\nMetrics:\n\n");
 
-       for (node = rb_first(&groups.entries); node; node = next) {
+       for (node = rb_first_cached(&groups.entries); node; node = next) {
                struct mep *me = container_of(node, struct mep, nd);
 
                if (metricgroups)
index f272e181d3d651dcf1e6b75db246aed7b072472a..376e86cb4c3c5facc467a01622d4287b5be9a7ad 100644 (file)
@@ -140,7 +140,7 @@ struct __name##_sorted *__name = __name##_sorted__new
 
 /* For 'struct intlist' */
 #define DECLARE_RESORT_RB_INTLIST(__name, __ilist)                             \
-       DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries,                     \
+       DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries.rb_root,             \
                                  __ilist->rblist.nr_entries)
 
 /* For 'struct machine->threads' */
index 0efc3258c64865f0a6174280842e34c9447691da..11e07fab20dc17f91c8005b77b6585648f78862c 100644 (file)
@@ -13,8 +13,9 @@
 
 int rblist__add_node(struct rblist *rblist, const void *new_entry)
 {
-       struct rb_node **p = &rblist->entries.rb_node;
+       struct rb_node **p = &rblist->entries.rb_root.rb_node;
        struct rb_node *parent = NULL, *new_node;
+       bool leftmost = true;
 
        while (*p != NULL) {
                int rc;
@@ -24,8 +25,10 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry)
                rc = rblist->node_cmp(parent, new_entry);
                if (rc > 0)
                        p = &(*p)->rb_left;
-               else if (rc < 0)
+               else if (rc < 0) {
                        p = &(*p)->rb_right;
+                       leftmost = false;
+               }
                else
                        return -EEXIST;
        }
@@ -35,7 +38,7 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry)
                return -ENOMEM;
 
        rb_link_node(new_node, parent, p);
-       rb_insert_color(new_node, &rblist->entries);
+       rb_insert_color_cached(new_node, &rblist->entries, leftmost);
        ++rblist->nr_entries;
 
        return 0;
@@ -43,7 +46,7 @@ int rblist__add_node(struct rblist *rblist, const void *new_entry)
 
 void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
 {
-       rb_erase(rb_node, &rblist->entries);
+       rb_erase_cached(rb_node, &rblist->entries);
        --rblist->nr_entries;
        rblist->node_delete(rblist, rb_node);
 }
@@ -52,8 +55,9 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist,
                                         const void *entry,
                                         bool create)
 {
-       struct rb_node **p = &rblist->entries.rb_node;
+       struct rb_node **p = &rblist->entries.rb_root.rb_node;
        struct rb_node *parent = NULL, *new_node = NULL;
+       bool leftmost = true;
 
        while (*p != NULL) {
                int rc;
@@ -63,8 +67,10 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist,
                rc = rblist->node_cmp(parent, entry);
                if (rc > 0)
                        p = &(*p)->rb_left;
-               else if (rc < 0)
+               else if (rc < 0) {
                        p = &(*p)->rb_right;
+                       leftmost = false;
+               }
                else
                        return parent;
        }
@@ -73,7 +79,8 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist,
                new_node = rblist->node_new(rblist, entry);
                if (new_node) {
                        rb_link_node(new_node, parent, p);
-                       rb_insert_color(new_node, &rblist->entries);
+                       rb_insert_color_cached(new_node,
+                                              &rblist->entries, leftmost);
                        ++rblist->nr_entries;
                }
        }
@@ -94,7 +101,7 @@ struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
 void rblist__init(struct rblist *rblist)
 {
        if (rblist != NULL) {
-               rblist->entries  = RB_ROOT;
+               rblist->entries  = RB_ROOT_CACHED;
                rblist->nr_entries = 0;
        }
 
@@ -103,7 +110,7 @@ void rblist__init(struct rblist *rblist)
 
 void rblist__exit(struct rblist *rblist)
 {
-       struct rb_node *pos, *next = rb_first(&rblist->entries);
+       struct rb_node *pos, *next = rb_first_cached(&rblist->entries);
 
        while (next) {
                pos = next;
@@ -124,7 +131,8 @@ struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx)
 {
        struct rb_node *node;
 
-       for (node = rb_first(&rblist->entries); node; node = rb_next(node)) {
+       for (node = rb_first_cached(&rblist->entries); node;
+            node = rb_next(node)) {
                if (!idx--)
                        return node;
        }
index 76df15c27f5fc67d581d9fe2370ffddceaeea46b..14b232a4d0b6d5a56016d599218ffa30ae7fc7cf 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 struct rblist {
-       struct rb_root entries;
+       struct rb_root_cached entries;
        unsigned int   nr_entries;
 
        int (*node_cmp)(struct rb_node *rbn, const void *entry);
index 3c22c58b3e9082f26d1818f1a0ad9c7fe50ce7ff..83d8094be4fe8cefe6442ba639a31a57a2f7548f 100644 (file)
@@ -168,7 +168,7 @@ static void reset_stat(struct runtime_stat *st)
        struct rb_node *pos, *next;
 
        rblist = &st->value_list;
-       next = rb_first(&rblist->entries);
+       next = rb_first_cached(&rblist->entries);
        while (next) {
                pos = next;
                next = rb_next(pos);
index d58f1e08b170b43c5ddfe3e77fdac13f6181d20f..7e82c71dcc422d7ebdb81bcd0b2bc7c4653b64aa 100644 (file)
@@ -57,7 +57,7 @@ static inline unsigned int strlist__nr_entries(const struct strlist *slist)
 /* For strlist iteration */
 static inline struct str_node *strlist__first(struct strlist *slist)
 {
-       struct rb_node *rn = rb_first(&slist->rblist.entries);
+       struct rb_node *rn = rb_first_cached(&slist->rblist.entries);
        return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
 }
 static inline struct str_node *strlist__next(struct str_node *sn)