aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2018-12-06 14:18:14 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-01-25 09:12:09 -0500
commitf3acb3a8a2081344801974ac5ec8e1b0d6f0ef36 (patch)
tree0bc3576849c9ff99905e7af40e9d5fb1bfa08249 /tools/perf/util
parent3aef2cad5d51ee66d2a614dd2f70cb34c74caf77 (diff)
perf machine: 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 operation dealing with machine->guests and threads->entries. The conversion is straightforward, however, it's worth noticing that the rb_erase_init() calls have been replaced by rb_erase_cached() which has no _init() flavor, however, the node is explicitly cleared next anyway, which was redundant until now. 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-3-dave@stgolabs.net Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/build-id.c12
-rw-r--r--tools/perf/util/machine.c53
-rw-r--r--tools/perf/util/machine.h12
-rw-r--r--tools/perf/util/rb_resort.h6
4 files changed, 48 insertions, 35 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 07ef7fad689c..2ff802068f06 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -364,7 +364,8 @@ int perf_session__write_buildid_table(struct perf_session *session,
364 if (err) 364 if (err)
365 return err; 365 return err;
366 366
367 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 367 for (nd = rb_first_cached(&session->machines.guests); nd;
368 nd = rb_next(nd)) {
368 struct machine *pos = rb_entry(nd, struct machine, rb_node); 369 struct machine *pos = rb_entry(nd, struct machine, rb_node);
369 err = machine__write_buildid_table(pos, fd); 370 err = machine__write_buildid_table(pos, fd);
370 if (err) 371 if (err)
@@ -397,7 +398,8 @@ int dsos__hit_all(struct perf_session *session)
397 if (err) 398 if (err)
398 return err; 399 return err;
399 400
400 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 401 for (nd = rb_first_cached(&session->machines.guests); nd;
402 nd = rb_next(nd)) {
401 struct machine *pos = rb_entry(nd, struct machine, rb_node); 403 struct machine *pos = rb_entry(nd, struct machine, rb_node);
402 404
403 err = machine__hit_all_dsos(pos); 405 err = machine__hit_all_dsos(pos);
@@ -850,7 +852,8 @@ int perf_session__cache_build_ids(struct perf_session *session)
850 852
851 ret = machine__cache_build_ids(&session->machines.host); 853 ret = machine__cache_build_ids(&session->machines.host);
852 854
853 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 855 for (nd = rb_first_cached(&session->machines.guests); nd;
856 nd = rb_next(nd)) {
854 struct machine *pos = rb_entry(nd, struct machine, rb_node); 857 struct machine *pos = rb_entry(nd, struct machine, rb_node);
855 ret |= machine__cache_build_ids(pos); 858 ret |= machine__cache_build_ids(pos);
856 } 859 }
@@ -867,7 +870,8 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
867 struct rb_node *nd; 870 struct rb_node *nd;
868 bool ret = machine__read_build_ids(&session->machines.host, with_hits); 871 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
869 872
870 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 873 for (nd = rb_first_cached(&session->machines.guests); nd;
874 nd = rb_next(nd)) {
871 struct machine *pos = rb_entry(nd, struct machine, rb_node); 875 struct machine *pos = rb_entry(nd, struct machine, rb_node);
872 ret |= machine__read_build_ids(pos, with_hits); 876 ret |= machine__read_build_ids(pos, with_hits);
873 } 877 }
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index ae85106bb5bf..66f019fdc510 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -42,7 +42,7 @@ static void machine__threads_init(struct machine *machine)
42 42
43 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 43 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
44 struct threads *threads = &machine->threads[i]; 44 struct threads *threads = &machine->threads[i];
45 threads->entries = RB_ROOT; 45 threads->entries = RB_ROOT_CACHED;
46 init_rwsem(&threads->lock); 46 init_rwsem(&threads->lock);
47 threads->nr = 0; 47 threads->nr = 0;
48 INIT_LIST_HEAD(&threads->dead); 48 INIT_LIST_HEAD(&threads->dead);
@@ -180,7 +180,7 @@ void machine__delete_threads(struct machine *machine)
180 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 180 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
181 struct threads *threads = &machine->threads[i]; 181 struct threads *threads = &machine->threads[i];
182 down_write(&threads->lock); 182 down_write(&threads->lock);
183 nd = rb_first(&threads->entries); 183 nd = rb_first_cached(&threads->entries);
184 while (nd) { 184 while (nd) {
185 struct thread *t = rb_entry(nd, struct thread, rb_node); 185 struct thread *t = rb_entry(nd, struct thread, rb_node);
186 186
@@ -223,7 +223,7 @@ void machine__delete(struct machine *machine)
223void machines__init(struct machines *machines) 223void machines__init(struct machines *machines)
224{ 224{
225 machine__init(&machines->host, "", HOST_KERNEL_ID); 225 machine__init(&machines->host, "", HOST_KERNEL_ID);
226 machines->guests = RB_ROOT; 226 machines->guests = RB_ROOT_CACHED;
227} 227}
228 228
229void machines__exit(struct machines *machines) 229void machines__exit(struct machines *machines)
@@ -235,9 +235,10 @@ void machines__exit(struct machines *machines)
235struct machine *machines__add(struct machines *machines, pid_t pid, 235struct machine *machines__add(struct machines *machines, pid_t pid,
236 const char *root_dir) 236 const char *root_dir)
237{ 237{
238 struct rb_node **p = &machines->guests.rb_node; 238 struct rb_node **p = &machines->guests.rb_root.rb_node;
239 struct rb_node *parent = NULL; 239 struct rb_node *parent = NULL;
240 struct machine *pos, *machine = malloc(sizeof(*machine)); 240 struct machine *pos, *machine = malloc(sizeof(*machine));
241 bool leftmost = true;
241 242
242 if (machine == NULL) 243 if (machine == NULL)
243 return NULL; 244 return NULL;
@@ -252,12 +253,14 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
252 pos = rb_entry(parent, struct machine, rb_node); 253 pos = rb_entry(parent, struct machine, rb_node);
253 if (pid < pos->pid) 254 if (pid < pos->pid)
254 p = &(*p)->rb_left; 255 p = &(*p)->rb_left;
255 else 256 else {
256 p = &(*p)->rb_right; 257 p = &(*p)->rb_right;
258 leftmost = false;
259 }
257 } 260 }
258 261
259 rb_link_node(&machine->rb_node, parent, p); 262 rb_link_node(&machine->rb_node, parent, p);
260 rb_insert_color(&machine->rb_node, &machines->guests); 263 rb_insert_color_cached(&machine->rb_node, &machines->guests, leftmost);
261 264
262 return machine; 265 return machine;
263} 266}
@@ -268,7 +271,7 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec)
268 271
269 machines->host.comm_exec = comm_exec; 272 machines->host.comm_exec = comm_exec;
270 273
271 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 274 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) {
272 struct machine *machine = rb_entry(nd, struct machine, rb_node); 275 struct machine *machine = rb_entry(nd, struct machine, rb_node);
273 276
274 machine->comm_exec = comm_exec; 277 machine->comm_exec = comm_exec;
@@ -277,7 +280,7 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec)
277 280
278struct machine *machines__find(struct machines *machines, pid_t pid) 281struct machine *machines__find(struct machines *machines, pid_t pid)
279{ 282{
280 struct rb_node **p = &machines->guests.rb_node; 283 struct rb_node **p = &machines->guests.rb_root.rb_node;
281 struct rb_node *parent = NULL; 284 struct rb_node *parent = NULL;
282 struct machine *machine; 285 struct machine *machine;
283 struct machine *default_machine = NULL; 286 struct machine *default_machine = NULL;
@@ -340,7 +343,7 @@ void machines__process_guests(struct machines *machines,
340{ 343{
341 struct rb_node *nd; 344 struct rb_node *nd;
342 345
343 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 346 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) {
344 struct machine *pos = rb_entry(nd, struct machine, rb_node); 347 struct machine *pos = rb_entry(nd, struct machine, rb_node);
345 process(pos, data); 348 process(pos, data);
346 } 349 }
@@ -353,7 +356,8 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
353 356
354 machines->host.id_hdr_size = id_hdr_size; 357 machines->host.id_hdr_size = id_hdr_size;
355 358
356 for (node = rb_first(&machines->guests); node; node = rb_next(node)) { 359 for (node = rb_first_cached(&machines->guests); node;
360 node = rb_next(node)) {
357 machine = rb_entry(node, struct machine, rb_node); 361 machine = rb_entry(node, struct machine, rb_node);
358 machine->id_hdr_size = id_hdr_size; 362 machine->id_hdr_size = id_hdr_size;
359 } 363 }
@@ -466,9 +470,10 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
466 pid_t pid, pid_t tid, 470 pid_t pid, pid_t tid,
467 bool create) 471 bool create)
468{ 472{
469 struct rb_node **p = &threads->entries.rb_node; 473 struct rb_node **p = &threads->entries.rb_root.rb_node;
470 struct rb_node *parent = NULL; 474 struct rb_node *parent = NULL;
471 struct thread *th; 475 struct thread *th;
476 bool leftmost = true;
472 477
473 th = threads__get_last_match(threads, machine, pid, tid); 478 th = threads__get_last_match(threads, machine, pid, tid);
474 if (th) 479 if (th)
@@ -486,8 +491,10 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
486 491
487 if (tid < th->tid) 492 if (tid < th->tid)
488 p = &(*p)->rb_left; 493 p = &(*p)->rb_left;
489 else 494 else {
490 p = &(*p)->rb_right; 495 p = &(*p)->rb_right;
496 leftmost = false;
497 }
491 } 498 }
492 499
493 if (!create) 500 if (!create)
@@ -496,7 +503,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
496 th = thread__new(pid, tid); 503 th = thread__new(pid, tid);
497 if (th != NULL) { 504 if (th != NULL) {
498 rb_link_node(&th->rb_node, parent, p); 505 rb_link_node(&th->rb_node, parent, p);
499 rb_insert_color(&th->rb_node, &threads->entries); 506 rb_insert_color_cached(&th->rb_node, &threads->entries, leftmost);
500 507
501 /* 508 /*
502 * We have to initialize map_groups separately 509 * We have to initialize map_groups separately
@@ -507,7 +514,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
507 * leader and that would screwed the rb tree. 514 * leader and that would screwed the rb tree.
508 */ 515 */
509 if (thread__init_map_groups(th, machine)) { 516 if (thread__init_map_groups(th, machine)) {
510 rb_erase_init(&th->rb_node, &threads->entries); 517 rb_erase_cached(&th->rb_node, &threads->entries);
511 RB_CLEAR_NODE(&th->rb_node); 518 RB_CLEAR_NODE(&th->rb_node);
512 thread__put(th); 519 thread__put(th);
513 return NULL; 520 return NULL;
@@ -798,7 +805,7 @@ size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
798 struct rb_node *nd; 805 struct rb_node *nd;
799 size_t ret = __dsos__fprintf(&machines->host.dsos.head, fp); 806 size_t ret = __dsos__fprintf(&machines->host.dsos.head, fp);
800 807
801 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 808 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) {
802 struct machine *pos = rb_entry(nd, struct machine, rb_node); 809 struct machine *pos = rb_entry(nd, struct machine, rb_node);
803 ret += __dsos__fprintf(&pos->dsos.head, fp); 810 ret += __dsos__fprintf(&pos->dsos.head, fp);
804 } 811 }
@@ -818,7 +825,7 @@ size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
818 struct rb_node *nd; 825 struct rb_node *nd;
819 size_t ret = machine__fprintf_dsos_buildid(&machines->host, fp, skip, parm); 826 size_t ret = machine__fprintf_dsos_buildid(&machines->host, fp, skip, parm);
820 827
821 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 828 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) {
822 struct machine *pos = rb_entry(nd, struct machine, rb_node); 829 struct machine *pos = rb_entry(nd, struct machine, rb_node);
823 ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm); 830 ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
824 } 831 }
@@ -858,7 +865,8 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)
858 865
859 ret = fprintf(fp, "Threads: %u\n", threads->nr); 866 ret = fprintf(fp, "Threads: %u\n", threads->nr);
860 867
861 for (nd = rb_first(&threads->entries); nd; nd = rb_next(nd)) { 868 for (nd = rb_first_cached(&threads->entries); nd;
869 nd = rb_next(nd)) {
862 struct thread *pos = rb_entry(nd, struct thread, rb_node); 870 struct thread *pos = rb_entry(nd, struct thread, rb_node);
863 871
864 ret += thread__fprintf(pos, fp); 872 ret += thread__fprintf(pos, fp);
@@ -1161,7 +1169,7 @@ failure:
1161 1169
1162void machines__destroy_kernel_maps(struct machines *machines) 1170void machines__destroy_kernel_maps(struct machines *machines)
1163{ 1171{
1164 struct rb_node *next = rb_first(&machines->guests); 1172 struct rb_node *next = rb_first_cached(&machines->guests);
1165 1173
1166 machine__destroy_kernel_maps(&machines->host); 1174 machine__destroy_kernel_maps(&machines->host);
1167 1175
@@ -1169,7 +1177,7 @@ void machines__destroy_kernel_maps(struct machines *machines)
1169 struct machine *pos = rb_entry(next, struct machine, rb_node); 1177 struct machine *pos = rb_entry(next, struct machine, rb_node);
1170 1178
1171 next = rb_next(&pos->rb_node); 1179 next = rb_next(&pos->rb_node);
1172 rb_erase(&pos->rb_node, &machines->guests); 1180 rb_erase_cached(&pos->rb_node, &machines->guests);
1173 machine__delete(pos); 1181 machine__delete(pos);
1174 } 1182 }
1175} 1183}
@@ -1734,7 +1742,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1734 BUG_ON(refcount_read(&th->refcnt) == 0); 1742 BUG_ON(refcount_read(&th->refcnt) == 0);
1735 if (lock) 1743 if (lock)
1736 down_write(&threads->lock); 1744 down_write(&threads->lock);
1737 rb_erase_init(&th->rb_node, &threads->entries); 1745 rb_erase_cached(&th->rb_node, &threads->entries);
1738 RB_CLEAR_NODE(&th->rb_node); 1746 RB_CLEAR_NODE(&th->rb_node);
1739 --threads->nr; 1747 --threads->nr;
1740 /* 1748 /*
@@ -2511,7 +2519,8 @@ int machine__for_each_thread(struct machine *machine,
2511 2519
2512 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 2520 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
2513 threads = &machine->threads[i]; 2521 threads = &machine->threads[i];
2514 for (nd = rb_first(&threads->entries); nd; nd = rb_next(nd)) { 2522 for (nd = rb_first_cached(&threads->entries); nd;
2523 nd = rb_next(nd)) {
2515 thread = rb_entry(nd, struct thread, rb_node); 2524 thread = rb_entry(nd, struct thread, rb_node);
2516 rc = fn(thread, priv); 2525 rc = fn(thread, priv);
2517 if (rc != 0) 2526 if (rc != 0)
@@ -2538,7 +2547,7 @@ int machines__for_each_thread(struct machines *machines,
2538 if (rc != 0) 2547 if (rc != 0)
2539 return rc; 2548 return rc;
2540 2549
2541 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 2550 for (nd = rb_first_cached(&machines->guests); nd; nd = rb_next(nd)) {
2542 struct machine *machine = rb_entry(nd, struct machine, rb_node); 2551 struct machine *machine = rb_entry(nd, struct machine, rb_node);
2543 2552
2544 rc = machine__for_each_thread(machine, fn, priv); 2553 rc = machine__for_each_thread(machine, fn, priv);
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 4ecd380ce1b4..e2f3df45410a 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -29,11 +29,11 @@ struct vdso_info;
29#define THREADS__TABLE_SIZE (1 << THREADS__TABLE_BITS) 29#define THREADS__TABLE_SIZE (1 << THREADS__TABLE_BITS)
30 30
31struct threads { 31struct threads {
32 struct rb_root entries; 32 struct rb_root_cached entries;
33 struct rw_semaphore lock; 33 struct rw_semaphore lock;
34 unsigned int nr; 34 unsigned int nr;
35 struct list_head dead; 35 struct list_head dead;
36 struct thread *last_match; 36 struct thread *last_match;
37}; 37};
38 38
39struct machine { 39struct machine {
@@ -140,7 +140,7 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);
140 140
141struct machines { 141struct machines {
142 struct machine host; 142 struct machine host;
143 struct rb_root guests; 143 struct rb_root_cached guests;
144}; 144};
145 145
146void machines__init(struct machines *machines); 146void machines__init(struct machines *machines);
diff --git a/tools/perf/util/rb_resort.h b/tools/perf/util/rb_resort.h
index a920f702a74d..f272e181d3d6 100644
--- a/tools/perf/util/rb_resort.h
+++ b/tools/perf/util/rb_resort.h
@@ -144,8 +144,8 @@ struct __name##_sorted *__name = __name##_sorted__new
144 __ilist->rblist.nr_entries) 144 __ilist->rblist.nr_entries)
145 145
146/* For 'struct machine->threads' */ 146/* For 'struct machine->threads' */
147#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine, hash_bucket) \ 147#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine, hash_bucket) \
148 DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries, \ 148 DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries.rb_root, \
149 __machine->threads[hash_bucket].nr) 149 __machine->threads[hash_bucket].nr)
150 150
151#endif /* _PERF_RESORT_RB_H_ */ 151#endif /* _PERF_RESORT_RB_H_ */