aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2012-10-08 19:31:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:22:37 -0400
commitdadf93534f125b9eda486b471446a8456a603d27 (patch)
tree4d796ac97a940683d008fdcb2040dc84d1405970
parent4f035ad67f4633c233cb3642711d49b4efc9c82d (diff)
rbtree: augmented rbtree test
Small test to measure the performance of augmented rbtrees. Signed-off-by: Michel Lespinasse <walken@google.com> Acked-by: Rik van Riel <riel@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--lib/rbtree_test.c103
1 files changed, 101 insertions, 2 deletions
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
index fd09465d82ca..66e41d4bfc39 100644
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -10,6 +10,10 @@
10struct test_node { 10struct test_node {
11 struct rb_node rb; 11 struct rb_node rb;
12 u32 key; 12 u32 key;
13
14 /* following fields used for testing augmented rbtree functionality */
15 u32 val;
16 u32 augmented;
13}; 17};
14 18
15static struct rb_root root = RB_ROOT; 19static struct rb_root root = RB_ROOT;
@@ -20,10 +24,11 @@ static struct rnd_state rnd;
20static void insert(struct test_node *node, struct rb_root *root) 24static void insert(struct test_node *node, struct rb_root *root)
21{ 25{
22 struct rb_node **new = &root->rb_node, *parent = NULL; 26 struct rb_node **new = &root->rb_node, *parent = NULL;
27 u32 key = node->key;
23 28
24 while (*new) { 29 while (*new) {
25 parent = *new; 30 parent = *new;
26 if (node->key < rb_entry(parent, struct test_node, rb)->key) 31 if (key < rb_entry(parent, struct test_node, rb)->key)
27 new = &parent->rb_left; 32 new = &parent->rb_left;
28 else 33 else
29 new = &parent->rb_right; 34 new = &parent->rb_right;
@@ -38,11 +43,62 @@ static inline void erase(struct test_node *node, struct rb_root *root)
38 rb_erase(&node->rb, root); 43 rb_erase(&node->rb, root);
39} 44}
40 45
46static inline u32 augment_recompute(struct test_node *node)
47{
48 u32 max = node->val, child_augmented;
49 if (node->rb.rb_left) {
50 child_augmented = rb_entry(node->rb.rb_left, struct test_node,
51 rb)->augmented;
52 if (max < child_augmented)
53 max = child_augmented;
54 }
55 if (node->rb.rb_right) {
56 child_augmented = rb_entry(node->rb.rb_right, struct test_node,
57 rb)->augmented;
58 if (max < child_augmented)
59 max = child_augmented;
60 }
61 return max;
62}
63
64static void augment_callback(struct rb_node *rb, void *unused)
65{
66 struct test_node *node = rb_entry(rb, struct test_node, rb);
67 node->augmented = augment_recompute(node);
68}
69
70static void insert_augmented(struct test_node *node, struct rb_root *root)
71{
72 struct rb_node **new = &root->rb_node, *parent = NULL;
73 u32 key = node->key;
74
75 while (*new) {
76 parent = *new;
77 if (key < rb_entry(parent, struct test_node, rb)->key)
78 new = &parent->rb_left;
79 else
80 new = &parent->rb_right;
81 }
82
83 rb_link_node(&node->rb, parent, new);
84 rb_insert_color(&node->rb, root);
85 rb_augment_insert(&node->rb, augment_callback, NULL);
86}
87
88static void erase_augmented(struct test_node *node, struct rb_root *root)
89{
90 struct rb_node *deepest = rb_augment_erase_begin(&node->rb);
91 rb_erase(&node->rb, root);
92 rb_augment_erase_end(deepest, augment_callback, NULL);
93}
94
41static void init(void) 95static void init(void)
42{ 96{
43 int i; 97 int i;
44 for (i = 0; i < NODES; i++) 98 for (i = 0; i < NODES; i++) {
45 nodes[i].key = prandom32(&rnd); 99 nodes[i].key = prandom32(&rnd);
100 nodes[i].val = prandom32(&rnd);
101 }
46} 102}
47 103
48static bool is_red(struct rb_node *rb) 104static bool is_red(struct rb_node *rb)
@@ -81,6 +137,17 @@ static void check(int nr_nodes)
81 WARN_ON_ONCE(count != nr_nodes); 137 WARN_ON_ONCE(count != nr_nodes);
82} 138}
83 139
140static void check_augmented(int nr_nodes)
141{
142 struct rb_node *rb;
143
144 check(nr_nodes);
145 for (rb = rb_first(&root); rb; rb = rb_next(rb)) {
146 struct test_node *node = rb_entry(rb, struct test_node, rb);
147 WARN_ON_ONCE(node->augmented != augment_recompute(node));
148 }
149}
150
84static int rbtree_test_init(void) 151static int rbtree_test_init(void)
85{ 152{
86 int i, j; 153 int i, j;
@@ -119,6 +186,38 @@ static int rbtree_test_init(void)
119 check(0); 186 check(0);
120 } 187 }
121 188
189 printk(KERN_ALERT "augmented rbtree testing");
190
191 init();
192
193 time1 = get_cycles();
194
195 for (i = 0; i < PERF_LOOPS; i++) {
196 for (j = 0; j < NODES; j++)
197 insert_augmented(nodes + j, &root);
198 for (j = 0; j < NODES; j++)
199 erase_augmented(nodes + j, &root);
200 }
201
202 time2 = get_cycles();
203 time = time2 - time1;
204
205 time = div_u64(time, PERF_LOOPS);
206 printk(" -> %llu cycles\n", (unsigned long long)time);
207
208 for (i = 0; i < CHECK_LOOPS; i++) {
209 init();
210 for (j = 0; j < NODES; j++) {
211 check_augmented(j);
212 insert_augmented(nodes + j, &root);
213 }
214 for (j = 0; j < NODES; j++) {
215 check_augmented(NODES - j);
216 erase_augmented(nodes + j, &root);
217 }
218 check_augmented(0);
219 }
220
122 return -EAGAIN; /* Fail will directly unload the module */ 221 return -EAGAIN; /* Fail will directly unload the module */
123} 222}
124 223