diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-12 21:31:04 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-12 21:31:04 -0500 |
commit | 59e994b7e98fe80febdb4b613fc12db484f88977 (patch) | |
tree | 1a6856aa169f0e75d8ba3e3c5f96c7d7b9750f84 | |
parent | d092a070a76d943d708497bd75c5097b7c622524 (diff) |
parse-events: Replace the event list with a sorted array
Replace the event list in the pevent structure with a sorted array
of event_format pointers. Now the search for an event can be done
with a binary search. With the size of events growing, this makes
a big difference.
Running trace-cmd report on a 300,000 event data file and outputing
into /dev/null, went from:
real 0m5.639s
user 0m5.464s
sys 0m0.174s
to
real 0m1.810s
user 0m1.672s
sys 0m0.138s
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | parse-events.c | 87 | ||||
-rw-r--r-- | parse-events.h | 5 |
2 files changed, 59 insertions, 33 deletions
diff --git a/parse-events.c b/parse-events.c index c5e8080..761e27c 100644 --- a/parse-events.c +++ b/parse-events.c | |||
@@ -562,8 +562,27 @@ enum event_type { | |||
562 | 562 | ||
563 | static void add_event(struct pevent *pevent, struct event_format *event) | 563 | static void add_event(struct pevent *pevent, struct event_format *event) |
564 | { | 564 | { |
565 | event->next = pevent->event_list; | 565 | int i; |
566 | pevent->event_list = event; | 566 | |
567 | if (!pevent->events) | ||
568 | pevent->events = malloc_or_die(sizeof(event)); | ||
569 | else | ||
570 | pevent->events = | ||
571 | realloc(pevent->events, sizeof(event) * | ||
572 | (pevent->nr_events + 1)); | ||
573 | if (!pevent->events) | ||
574 | die("Can not allocate events"); | ||
575 | |||
576 | for (i = 0; i < pevent->nr_events; i++) { | ||
577 | if (pevent->events[i]->id > event->id) | ||
578 | break; | ||
579 | } | ||
580 | if (i < pevent->nr_events) | ||
581 | memmove(&pevent->events[i + 1], | ||
582 | &pevent->events[i], | ||
583 | sizeof(event) * (pevent->nr_events - i)); | ||
584 | |||
585 | pevent->events[i] = event; | ||
567 | pevent->nr_events++; | 586 | pevent->nr_events++; |
568 | 587 | ||
569 | event->pevent = pevent; | 588 | event->pevent = pevent; |
@@ -2470,10 +2489,10 @@ static int get_common_info(struct pevent *pevent, | |||
2470 | * All events should have the same common elements. | 2489 | * All events should have the same common elements. |
2471 | * Pick any event to find where the type is; | 2490 | * Pick any event to find where the type is; |
2472 | */ | 2491 | */ |
2473 | if (!pevent->event_list) | 2492 | if (!pevent->events) |
2474 | die("no event_list!"); | 2493 | die("no event_list!"); |
2475 | 2494 | ||
2476 | event = pevent->event_list; | 2495 | event = pevent->events[0]; |
2477 | field = pevent_find_common_field(event, type); | 2496 | field = pevent_find_common_field(event, type); |
2478 | if (!field) | 2497 | if (!field) |
2479 | die("field '%s' not found", type); | 2498 | die("field '%s' not found", type); |
@@ -2538,6 +2557,8 @@ static int parse_common_lock_depth(struct pevent *pevent, void *data) | |||
2538 | return ret; | 2557 | return ret; |
2539 | } | 2558 | } |
2540 | 2559 | ||
2560 | static int events_id_cmp(const void *a, const void *b); | ||
2561 | |||
2541 | /** | 2562 | /** |
2542 | * pevent_find_event - find an event by given id | 2563 | * pevent_find_event - find an event by given id |
2543 | * @pevent: a handle to the pevent | 2564 | * @pevent: a handle to the pevent |
@@ -2547,13 +2568,19 @@ static int parse_common_lock_depth(struct pevent *pevent, void *data) | |||
2547 | */ | 2568 | */ |
2548 | struct event_format *pevent_find_event(struct pevent *pevent, int id) | 2569 | struct event_format *pevent_find_event(struct pevent *pevent, int id) |
2549 | { | 2570 | { |
2550 | struct event_format *event; | 2571 | struct event_format **eventptr; |
2572 | struct event_format key; | ||
2573 | struct event_format *pkey = &key; | ||
2551 | 2574 | ||
2552 | for (event = pevent->event_list; event; event = event->next) { | 2575 | key.id = id; |
2553 | if (event->id == id) | 2576 | |
2554 | break; | 2577 | eventptr = bsearch(&pkey, pevent->events, pevent->nr_events, |
2555 | } | 2578 | sizeof(*pevent->events), events_id_cmp); |
2556 | return event; | 2579 | |
2580 | if (eventptr) | ||
2581 | return *eventptr; | ||
2582 | |||
2583 | return NULL; | ||
2557 | } | 2584 | } |
2558 | 2585 | ||
2559 | /** | 2586 | /** |
@@ -2570,8 +2597,10 @@ pevent_find_event_by_name(struct pevent *pevent, | |||
2570 | const char *sys, const char *name) | 2597 | const char *sys, const char *name) |
2571 | { | 2598 | { |
2572 | struct event_format *event; | 2599 | struct event_format *event; |
2600 | int i; | ||
2573 | 2601 | ||
2574 | for (event = pevent->event_list; event; event = event->next) { | 2602 | for (i = 0; i < pevent->nr_events; i++) { |
2603 | event = pevent->events[i]; | ||
2575 | if (strcmp(event->name, name) == 0) { | 2604 | if (strcmp(event->name, name) == 0) { |
2576 | if (!sys) | 2605 | if (!sys) |
2577 | break; | 2606 | break; |
@@ -2579,6 +2608,9 @@ pevent_find_event_by_name(struct pevent *pevent, | |||
2579 | break; | 2608 | break; |
2580 | } | 2609 | } |
2581 | } | 2610 | } |
2611 | if (i == pevent->nr_events) | ||
2612 | event = NULL; | ||
2613 | |||
2582 | return event; | 2614 | return event; |
2583 | } | 2615 | } |
2584 | 2616 | ||
@@ -3257,7 +3289,7 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
3257 | struct event_format *event; | 3289 | struct event_format *event; |
3258 | 3290 | ||
3259 | check_lock_depth = 0; | 3291 | check_lock_depth = 0; |
3260 | event = pevent->event_list; | 3292 | event = pevent->events[0]; |
3261 | field = pevent_find_common_field(event, "common_lock_depth"); | 3293 | field = pevent_find_common_field(event, "common_lock_depth"); |
3262 | if (field) | 3294 | if (field) |
3263 | lock_depth_exists = 1; | 3295 | lock_depth_exists = 1; |
@@ -3474,11 +3506,10 @@ static int events_system_cmp(const void *a, const void *b) | |||
3474 | struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type) | 3506 | struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type) |
3475 | { | 3507 | { |
3476 | struct event_format **events; | 3508 | struct event_format **events; |
3477 | struct event_format *event; | ||
3478 | int (*sort)(const void *a, const void *b); | 3509 | int (*sort)(const void *a, const void *b); |
3479 | int i = 0; | 3510 | int i = 0; |
3480 | 3511 | ||
3481 | events = pevent->events; | 3512 | events = pevent->sort_events; |
3482 | 3513 | ||
3483 | if (events && pevent->last_type == sort_type) | 3514 | if (events && pevent->last_type == sort_type) |
3484 | return events; | 3515 | return events; |
@@ -3488,17 +3519,16 @@ struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_ | |||
3488 | if (!events) | 3519 | if (!events) |
3489 | return NULL; | 3520 | return NULL; |
3490 | 3521 | ||
3491 | for (event = pevent->event_list; event; event = event->next) { | 3522 | memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events); |
3492 | if (i == pevent->nr_events) { | ||
3493 | warning("Wrong event count"); | ||
3494 | free(events); | ||
3495 | return NULL; | ||
3496 | } | ||
3497 | events[i++] = event; | ||
3498 | } | ||
3499 | events[i] = NULL; | 3523 | events[i] = NULL; |
3500 | 3524 | ||
3501 | pevent->events = events; | 3525 | pevent->sort_events = events; |
3526 | |||
3527 | /* the internal events are sorted by id */ | ||
3528 | if (sort_type == EVENT_SORT_ID) { | ||
3529 | pevent->last_type = sort_type; | ||
3530 | return events; | ||
3531 | } | ||
3502 | } | 3532 | } |
3503 | 3533 | ||
3504 | switch (sort_type) { | 3534 | switch (sort_type) { |
@@ -3890,7 +3920,6 @@ static void free_event(struct event_format *event) | |||
3890 | */ | 3920 | */ |
3891 | void pevent_free(struct pevent *pevent) | 3921 | void pevent_free(struct pevent *pevent) |
3892 | { | 3922 | { |
3893 | struct event_format *event, *next_event; | ||
3894 | struct cmdline_list *cmdlist = pevent->cmdlist, *cmdnext; | 3923 | struct cmdline_list *cmdlist = pevent->cmdlist, *cmdnext; |
3895 | struct func_list *funclist = pevent->funclist, *funcnext; | 3924 | struct func_list *funclist = pevent->funclist, *funcnext; |
3896 | struct printk_list *printklist = pevent->printklist, *printknext; | 3925 | struct printk_list *printklist = pevent->printklist, *printknext; |
@@ -3942,13 +3971,11 @@ void pevent_free(struct pevent *pevent) | |||
3942 | printklist = printknext; | 3971 | printklist = printknext; |
3943 | } | 3972 | } |
3944 | 3973 | ||
3945 | free(pevent->events); | 3974 | for (i = 0; i < pevent->nr_events; i++) |
3946 | 3975 | free_event(pevent->events[i]); | |
3947 | for (event = pevent->event_list; event; event = next_event) { | ||
3948 | next_event = event->next; | ||
3949 | 3976 | ||
3950 | free_event(event); | 3977 | free(pevent->events); |
3951 | } | 3978 | free(pevent->sort_events); |
3952 | 3979 | ||
3953 | free(pevent); | 3980 | free(pevent); |
3954 | } | 3981 | } |
diff --git a/parse-events.h b/parse-events.h index 66e0eb5..3a6bf5b 100644 --- a/parse-events.h +++ b/parse-events.h | |||
@@ -194,7 +194,6 @@ struct print_fmt { | |||
194 | }; | 194 | }; |
195 | 195 | ||
196 | struct event_format { | 196 | struct event_format { |
197 | struct event_format *next; | ||
198 | struct pevent *pevent; | 197 | struct pevent *pevent; |
199 | char *name; | 198 | char *name; |
200 | int id; | 199 | int id; |
@@ -258,9 +257,9 @@ struct pevent { | |||
258 | struct printk_list *printklist; | 257 | struct printk_list *printklist; |
259 | unsigned int printk_count; | 258 | unsigned int printk_count; |
260 | 259 | ||
261 | struct event_format *event_list; | ||
262 | int nr_events; | ||
263 | struct event_format **events; | 260 | struct event_format **events; |
261 | int nr_events; | ||
262 | struct event_format **sort_events; | ||
264 | enum event_sort_type last_type; | 263 | enum event_sort_type last_type; |
265 | 264 | ||
266 | int type_offset; | 265 | int type_offset; |