Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf callchain: Use cached rbtrees

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>

authored by

Davidlohr Bueso and committed by
Arnaldo Carvalho de Melo
55ecd631 f3acb3a8

+36 -28
+2 -2
tools/perf/util/dso.c
··· 1199 1199 dso__set_short_name(dso, dso->name, false); 1200 1200 dso->symbols = dso->symbol_names = RB_ROOT; 1201 1201 dso->data.cache = RB_ROOT; 1202 - dso->inlined_nodes = RB_ROOT; 1203 - dso->srclines = RB_ROOT; 1202 + dso->inlined_nodes = RB_ROOT_CACHED; 1203 + dso->srclines = RB_ROOT_CACHED; 1204 1204 dso->data.fd = -1; 1205 1205 dso->data.status = DSO_DATA_STATUS_UNKNOWN; 1206 1206 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
+2 -2
tools/perf/util/dso.h
··· 143 143 struct rb_root *root; /* root of rbtree that rb_node is in */ 144 144 struct rb_root symbols; 145 145 struct rb_root symbol_names; 146 - struct rb_root inlined_nodes; 147 - struct rb_root srclines; 146 + struct rb_root_cached inlined_nodes; 147 + struct rb_root_cached srclines; 148 148 struct { 149 149 u64 addr; 150 150 struct symbol *symbol;
+25 -18
tools/perf/util/srcline.c
··· 594 594 struct rb_node rb_node; 595 595 }; 596 596 597 - void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline) 597 + void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline) 598 598 { 599 - struct rb_node **p = &tree->rb_node; 599 + struct rb_node **p = &tree->rb_root.rb_node; 600 600 struct rb_node *parent = NULL; 601 601 struct srcline_node *i, *node; 602 + bool leftmost = true; 602 603 603 604 node = zalloc(sizeof(struct srcline_node)); 604 605 if (!node) { ··· 615 614 i = rb_entry(parent, struct srcline_node, rb_node); 616 615 if (addr < i->addr) 617 616 p = &(*p)->rb_left; 618 - else 617 + else { 619 618 p = &(*p)->rb_right; 619 + leftmost = false; 620 + } 620 621 } 621 622 rb_link_node(&node->rb_node, parent, p); 622 - rb_insert_color(&node->rb_node, tree); 623 + rb_insert_color_cached(&node->rb_node, tree, leftmost); 623 624 } 624 625 625 - char *srcline__tree_find(struct rb_root *tree, u64 addr) 626 + char *srcline__tree_find(struct rb_root_cached *tree, u64 addr) 626 627 { 627 - struct rb_node *n = tree->rb_node; 628 + struct rb_node *n = tree->rb_root.rb_node; 628 629 629 630 while (n) { 630 631 struct srcline_node *i = rb_entry(n, struct srcline_node, ··· 643 640 return NULL; 644 641 } 645 642 646 - void srcline__tree_delete(struct rb_root *tree) 643 + void srcline__tree_delete(struct rb_root_cached *tree) 647 644 { 648 645 struct srcline_node *pos; 649 - struct rb_node *next = rb_first(tree); 646 + struct rb_node *next = rb_first_cached(tree); 650 647 651 648 while (next) { 652 649 pos = rb_entry(next, struct srcline_node, rb_node); 653 650 next = rb_next(&pos->rb_node); 654 - rb_erase(&pos->rb_node, tree); 651 + rb_erase_cached(&pos->rb_node, tree); 655 652 free_srcline(pos->srcline); 656 653 zfree(&pos); 657 654 } ··· 685 682 free(node); 686 683 } 687 684 688 - void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines) 685 + void inlines__tree_insert(struct rb_root_cached *tree, 686 + struct inline_node *inlines) 689 687 { 690 - struct rb_node **p = &tree->rb_node; 688 + struct rb_node **p = &tree->rb_root.rb_node; 691 689 struct rb_node *parent = NULL; 692 690 const u64 addr = inlines->addr; 693 691 struct inline_node *i; 692 + bool leftmost = true; 694 693 695 694 while (*p != NULL) { 696 695 parent = *p; 697 696 i = rb_entry(parent, struct inline_node, rb_node); 698 697 if (addr < i->addr) 699 698 p = &(*p)->rb_left; 700 - else 699 + else { 701 700 p = &(*p)->rb_right; 701 + leftmost = false; 702 + } 702 703 } 703 704 rb_link_node(&inlines->rb_node, parent, p); 704 - rb_insert_color(&inlines->rb_node, tree); 705 + rb_insert_color_cached(&inlines->rb_node, tree, leftmost); 705 706 } 706 707 707 - struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr) 708 + struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr) 708 709 { 709 - struct rb_node *n = tree->rb_node; 710 + struct rb_node *n = tree->rb_root.rb_node; 710 711 711 712 while (n) { 712 713 struct inline_node *i = rb_entry(n, struct inline_node, ··· 727 720 return NULL; 728 721 } 729 722 730 - void inlines__tree_delete(struct rb_root *tree) 723 + void inlines__tree_delete(struct rb_root_cached *tree) 731 724 { 732 725 struct inline_node *pos; 733 - struct rb_node *next = rb_first(tree); 726 + struct rb_node *next = rb_first_cached(tree); 734 727 735 728 while (next) { 736 729 pos = rb_entry(next, struct inline_node, rb_node); 737 730 next = rb_next(&pos->rb_node); 738 - rb_erase(&pos->rb_node, tree); 731 + rb_erase_cached(&pos->rb_node, tree); 739 732 inline_node__delete(pos); 740 733 } 741 734 }
+7 -6
tools/perf/util/srcline.h
··· 19 19 char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line); 20 20 21 21 /* insert the srcline into the DSO, which will take ownership */ 22 - void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline); 22 + void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline); 23 23 /* find previously inserted srcline */ 24 - char *srcline__tree_find(struct rb_root *tree, u64 addr); 24 + char *srcline__tree_find(struct rb_root_cached *tree, u64 addr); 25 25 /* delete all srclines within the tree */ 26 - void srcline__tree_delete(struct rb_root *tree); 26 + void srcline__tree_delete(struct rb_root_cached *tree); 27 27 28 28 #define SRCLINE_UNKNOWN ((char *) "??:0") 29 29 ··· 46 46 void inline_node__delete(struct inline_node *node); 47 47 48 48 /* insert the inline node list into the DSO, which will take ownership */ 49 - void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines); 49 + void inlines__tree_insert(struct rb_root_cached *tree, 50 + struct inline_node *inlines); 50 51 /* find previously inserted inline node list */ 51 - struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr); 52 + struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr); 52 53 /* delete all nodes within the tree of inline_node s */ 53 - void inlines__tree_delete(struct rb_root *tree); 54 + void inlines__tree_delete(struct rb_root_cached *tree); 54 55 55 56 #endif /* PERF_SRCLINE_H */