diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-05 17:14:37 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-05 17:14:37 -0400 |
commit | 93290e83d330653f090b3780e59ea5d2bf1e3bca (patch) | |
tree | 084663110e9ef4fa1d306f3421deb675fb575d60 | |
parent | 8e74ea12a1fcbe0a799284163f0cf72bcb916df7 (diff) |
Rewrote set_cpu_to_rts() and iterate() for increased performance and accuracy.
Container job information functions, like displaying the job in the server's boxes
or the currently running task in pop-ups, rewritten to take advantage of these
changes.
-rw-r--r-- | rt-plot-container.c | 114 | ||||
-rw-r--r-- | rt-plot-vcpu.c | 28 | ||||
-rw-r--r-- | rt-plot.c | 178 | ||||
-rw-r--r-- | rt-plot.h | 2 | ||||
-rw-r--r-- | trace-dialog.c | 2 | ||||
-rw-r--r-- | trace-graph.c | 38 |
6 files changed, 188 insertions, 174 deletions
diff --git a/rt-plot-container.c b/rt-plot-container.c index 94f78ee..6c647fc 100644 --- a/rt-plot-container.c +++ b/rt-plot-container.c | |||
@@ -22,6 +22,80 @@ int rt_plot_get_containers(struct graph_info *ginfo, gint **conts, | |||
22 | return count; | 22 | return count; |
23 | } | 23 | } |
24 | 24 | ||
25 | struct record * | ||
26 | rt_read_next_data(struct graph_info *ginfo, struct tracecmd_input *handle, int *rec_cpu) | ||
27 | { | ||
28 | unsigned long long ts; | ||
29 | struct record *record; | ||
30 | int next; | ||
31 | int cpu; | ||
32 | |||
33 | if (rec_cpu) | ||
34 | *rec_cpu = -1; | ||
35 | |||
36 | next = -1; | ||
37 | ts = 0; | ||
38 | |||
39 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | ||
40 | record = tracecmd_peek_data(handle, cpu); | ||
41 | if (record && (!ts || get_rts(ginfo, record) < ts)) { | ||
42 | ts = get_rts(ginfo, record); | ||
43 | next = cpu; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | if (next >= 0) { | ||
48 | if (rec_cpu) | ||
49 | *rec_cpu = next; | ||
50 | return tracecmd_read_data(handle, next); | ||
51 | } | ||
52 | |||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | struct server_iter_args { | ||
57 | unsigned long long goal; | ||
58 | int match_sid; | ||
59 | |||
60 | int *out_job; | ||
61 | int *out_tid; | ||
62 | int *out_tjob; | ||
63 | int is_running; | ||
64 | }; | ||
65 | |||
66 | static int server_iterator(struct graph_info *ginfo, struct record *record, void *data) | ||
67 | { | ||
68 | int sid, job, tid, tjob, match; | ||
69 | struct server_iter_args *args = data; | ||
70 | unsigned long long when, time = get_rts(ginfo, record); | ||
71 | |||
72 | if (time > args->goal + max_rt_search(ginfo)) | ||
73 | return 0; | ||
74 | if (time < args->goal) | ||
75 | return 1; | ||
76 | |||
77 | #define ARGS ginfo, record, &sid, &job, &tid, &tjob, &when | ||
78 | match = rt_graph_check_server_switch_away(ARGS); | ||
79 | if (match && sid == args->match_sid) { | ||
80 | (*args->out_tid) = tid; | ||
81 | (*args->out_tjob) = tjob; | ||
82 | (*args->out_job) = job; | ||
83 | args->is_running = 1; | ||
84 | return 0; | ||
85 | |||
86 | } | ||
87 | |||
88 | match = rt_graph_check_server_switch_to(ARGS); | ||
89 | if (match && sid == args->match_sid) { | ||
90 | /* We must not have been running anything */ | ||
91 | (*args->out_job) = job; | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | #undef ARGS | ||
96 | return 1; | ||
97 | } | ||
98 | |||
25 | int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, | 99 | int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, |
26 | int match_sid, unsigned long long time, | 100 | int match_sid, unsigned long long time, |
27 | unsigned long long *out_release, | 101 | unsigned long long *out_release, |
@@ -29,47 +103,19 @@ int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, | |||
29 | int *out_job, int *out_tid, int *out_tjob, | 103 | int *out_job, int *out_tid, int *out_tjob, |
30 | struct record **out_record) | 104 | struct record **out_record) |
31 | { | 105 | { |
32 | struct record *record; | 106 | struct server_iter_args args = {time, match_sid, |
33 | int sid, job, tid, tjob, match, next_cpu, is_running = 0; | 107 | out_job, out_tid, out_tjob, 0}; |
34 | unsigned long long when, max_ts; | ||
35 | 108 | ||
36 | *out_record = find_rt_record(ginfo, rt, time); | 109 | *out_record = find_rt_record(ginfo, rt, time); |
37 | if (!(*out_record)) | 110 | if (!*out_record) |
38 | return 0; | 111 | return 0; |
39 | 112 | ||
40 | *out_release = *out_deadline = *out_job = *out_tid = 0; | 113 | *out_release = *out_deadline = *out_job = *out_tid = 0; |
41 | 114 | ||
42 | /* Get current job info for server task */ | 115 | set_cpus_to_rts(ginfo, time); |
43 | get_previous_release(ginfo, rt, sid, time, | 116 | iterate(ginfo, 0, server_iterator, &args); |
44 | out_job, out_release, out_deadline); | ||
45 | |||
46 | /* Need to reset back to current location */ | ||
47 | record = find_rt_record(ginfo, rt, time); | ||
48 | if (!record) | ||
49 | goto out; | ||
50 | |||
51 | /* TODO: read backwards too */ | ||
52 | max_ts = time + max_rt_search(ginfo); | ||
53 | do { | ||
54 | if (get_rts(ginfo, record) > max_ts) | ||
55 | break; | ||
56 | |||
57 | match = rt_graph_check_server_switch_away(ginfo, record, | ||
58 | &sid, &job, &tid, &tjob, | ||
59 | &when); | ||
60 | if (match && sid == match_sid) { | ||
61 | *out_tid = tid; | ||
62 | *out_tjob = tjob; | ||
63 | is_running = 1; | ||
64 | break; | ||
65 | } | ||
66 | free_record(record); | ||
67 | } while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))); | ||
68 | 117 | ||
69 | if (record && record != *out_record) | 118 | return args.is_running; |
70 | free_record(record); | ||
71 | out: | ||
72 | return is_running; | ||
73 | } | 119 | } |
74 | 120 | ||
75 | void rt_plot_container(struct graph_info *ginfo, int cid) | 121 | void rt_plot_container(struct graph_info *ginfo, int cid) |
diff --git a/rt-plot-vcpu.c b/rt-plot-vcpu.c index 8f850b9..e39ae19 100644 --- a/rt-plot-vcpu.c +++ b/rt-plot-vcpu.c | |||
@@ -13,12 +13,12 @@ | |||
13 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) | 13 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | static void update_tid(struct vcpu_info *info, int tid) | 16 | static void update_label(struct vcpu_info *info, int tid, int tjob) |
17 | { | 17 | { |
18 | info->fresh = FALSE; | 18 | info->fresh = FALSE; |
19 | if (tid != info->run_tid) { | 19 | if (tid != info->run_tid) { |
20 | info->run_tid = tid; | 20 | info->run_tid = tid; |
21 | snprintf(info->label, LLABEL, "%d", tid); | 21 | snprintf(info->label, LLABEL, "%d:%d", tid, tjob); |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
@@ -33,7 +33,7 @@ try_server_switch_away(struct graph_info *ginfo, struct vcpu_info *vcpu_info, | |||
33 | &sid, &job, | 33 | &sid, &job, |
34 | &tid, &tjob, &ts); | 34 | &tid, &tjob, &ts); |
35 | if (match && sid == vcpu_info->sid) { | 35 | if (match && sid == vcpu_info->sid) { |
36 | update_tid(vcpu_info, tid); | 36 | update_label(vcpu_info, tid, tjob); |
37 | 37 | ||
38 | if (vcpu_info->run_time && vcpu_info->run_time < ts) { | 38 | if (vcpu_info->run_time && vcpu_info->run_time < ts) { |
39 | info->box = TRUE; | 39 | info->box = TRUE; |
@@ -66,7 +66,7 @@ static int try_server_switch_to(struct graph_info *ginfo, struct vcpu_info *vcpu | |||
66 | match = rt_graph_check_server_switch_to(ginfo, record, | 66 | match = rt_graph_check_server_switch_to(ginfo, record, |
67 | &sid, &job, &tid, &tjob, &ts); | 67 | &sid, &job, &tid, &tjob, &ts); |
68 | if (match && sid == vcpu_info->sid) { | 68 | if (match && sid == vcpu_info->sid) { |
69 | update_tid(vcpu_info, tid); | 69 | update_label(vcpu_info, tid, tjob); |
70 | vcpu_info->run_time = ts; | 70 | vcpu_info->run_time = ts; |
71 | vcpu_info->run_cpu = record->cpu; | 71 | vcpu_info->run_cpu = record->cpu; |
72 | vcpu_info->run_tid = tid; | 72 | vcpu_info->run_tid = tid; |
@@ -151,7 +151,7 @@ static void do_plot_end(struct graph_info *ginfo, struct vcpu_info *vcpu_info, | |||
151 | &release, &deadline, | 151 | &release, &deadline, |
152 | &job, &tid, &tjob, &record); | 152 | &job, &tid, &tjob, &record); |
153 | if (is_running) { | 153 | if (is_running) { |
154 | update_tid(vcpu_info, tid); | 154 | update_label(vcpu_info, tid, tjob); |
155 | info->box = TRUE; | 155 | info->box = TRUE; |
156 | info->bcolor = hash_pid(vcpu_info->run_tid); | 156 | info->bcolor = hash_pid(vcpu_info->run_tid); |
157 | info->bfill = is_task_running(ginfo, ginfo->view_end_time, tid); | 157 | info->bfill = is_task_running(ginfo, ginfo->view_end_time, tid); |
@@ -251,7 +251,7 @@ void rt_vcpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | |||
251 | vcpu_info->fresh = TRUE; | 251 | vcpu_info->fresh = TRUE; |
252 | vcpu_info->running = FALSE; | 252 | vcpu_info->running = FALSE; |
253 | vcpu_info->last_job = -1; | 253 | vcpu_info->last_job = -1; |
254 | update_tid(vcpu_info, 0); | 254 | update_label(vcpu_info, 0, 0); |
255 | } | 255 | } |
256 | 256 | ||
257 | /** | 257 | /** |
@@ -276,15 +276,15 @@ int rt_vcpu_plot_record_matches(struct rt_plot_common *rt, | |||
276 | int dint, sid, match; | 276 | int dint, sid, match; |
277 | unsigned long long dull; | 277 | unsigned long long dull; |
278 | 278 | ||
279 | #define ARG ginfo, record, &sid | 279 | #define ARG ginfo, record, &sid, &dint |
280 | match = rt_graph_check_server_switch_to(ARG, &dint, &dint, &dint, &dull) || | 280 | match = rt_graph_check_server_switch_to(ARG, &dint, &dint, &dull) || |
281 | rt_graph_check_server_switch_away(ARG, &dint, &dint, &dint, &dull); | 281 | rt_graph_check_server_switch_away(ARG,&dint, &dint, &dull); |
282 | /* rt_graph_check_server_completion(ARG, &dint, &dull) || */ | 282 | rt_graph_check_server_completion(ARG, &dull) || |
283 | /* rt_graph_check_server_release(ARG, &dint, &dull, &dull); */ | 283 | rt_graph_check_server_release(ARG, &dull, &dull); |
284 | /* rt_graph_check_server_block(ARG, &dull) || */ | 284 | rt_graph_check_server_block(ARG, &dull) || |
285 | /* rt_graph_check_server_resume(ARG, &dull); */ | 285 | rt_graph_check_server_resume(ARG, &dull); |
286 | #undef ARG | 286 | #undef ARG |
287 | return (sid == vcpu_info->sid); | 287 | return (match && sid == vcpu_info->sid); |
288 | } | 288 | } |
289 | 289 | ||
290 | /** | 290 | /** |
@@ -28,15 +28,15 @@ void insert_record(struct graph_info *ginfo, struct record_list *list, | |||
28 | 28 | ||
29 | while (pos->next) { | 29 | while (pos->next) { |
30 | unsigned long long next_rts = get_rts(ginfo, pos->next->record); | 30 | unsigned long long next_rts = get_rts(ginfo, pos->next->record); |
31 | if (( reverse && !next_rts > get_rts(ginfo, record)) || | 31 | if (( reverse && next_rts < get_rts(ginfo, record)) || |
32 | (!reverse && next_rts < get_rts(ginfo, record))){ | 32 | (!reverse && next_rts > get_rts(ginfo, record))){ |
33 | break; | 33 | break; |
34 | } | 34 | } |
35 | pos = pos->next; | 35 | pos = pos->next; |
36 | } | 36 | } |
37 | 37 | ||
38 | node->next = pos->next; | 38 | node->next = pos->next; |
39 | pos->next = node; | 39 | pos->next = node; |
40 | } | 40 | } |
41 | 41 | ||
42 | 42 | ||
@@ -53,7 +53,7 @@ int pop_record(struct graph_info *ginfo, struct record_list *list, | |||
53 | list->next = list->next->next; | 53 | list->next = list->next->next; |
54 | (*node)->next = 0; | 54 | (*node)->next = 0; |
55 | 55 | ||
56 | return 1; | 56 | return 1; |
57 | } | 57 | } |
58 | 58 | ||
59 | 59 | ||
@@ -91,7 +91,7 @@ prev_release_iterator(struct graph_info *ginfo, struct record *rec, void *data) | |||
91 | *(args->out_job) = job; | 91 | *(args->out_job) = job; |
92 | *(args->out_release) = release; | 92 | *(args->out_release) = release; |
93 | *(args->out_deadline) = deadline; | 93 | *(args->out_deadline) = deadline; |
94 | 94 | ||
95 | /* Cache to minimize work later */ | 95 | /* Cache to minimize work later */ |
96 | args->common->last_job.no = job; | 96 | args->common->last_job.no = job; |
97 | args->common->last_job.release = release; | 97 | args->common->last_job.release = release; |
@@ -122,14 +122,14 @@ prev_display_iterator(struct graph_info *ginfo, struct record *record, void *dat | |||
122 | if (get_rts(ginfo, record) < args->min_ts) { | 122 | if (get_rts(ginfo, record) < args->min_ts) { |
123 | return 0; | 123 | return 0; |
124 | } | 124 | } |
125 | 125 | ||
126 | eid = pevent_data_type(ginfo->pevent, record); | 126 | eid = pevent_data_type(ginfo->pevent, record); |
127 | ignored = (eid == ginfo->event_sched_switch_id); | 127 | ignored = (eid == ginfo->event_sched_switch_id); |
128 | 128 | ||
129 | if (!ignored) { | 129 | if (!ignored) { |
130 | ignored = args->common->is_drawn(ginfo, eid); | 130 | ignored = args->common->is_drawn(ginfo, eid); |
131 | } | 131 | } |
132 | 132 | ||
133 | if (!ignored && args->common->record_matches(args->common, ginfo, record)) { | 133 | if (!ignored && args->common->record_matches(args->common, ginfo, record)) { |
134 | args->result = record; | 134 | args->result = record; |
135 | ++record->ref_count; | 135 | ++record->ref_count; |
@@ -147,8 +147,6 @@ static struct record* | |||
147 | find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info, | 147 | find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info, |
148 | unsigned long long time, unsigned long long range) | 148 | unsigned long long time, unsigned long long range) |
149 | { | 149 | { |
150 | int eid, ignored, match, cpu; | ||
151 | struct record *prev, *next, *res = NULL; | ||
152 | struct prev_display_args args = {rt_info, NULL, 0}; | 150 | struct prev_display_args args = {rt_info, NULL, 0}; |
153 | 151 | ||
154 | if (range) { | 152 | if (range) { |
@@ -342,98 +340,64 @@ rt_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, | |||
342 | return ret; | 340 | return ret; |
343 | } | 341 | } |
344 | 342 | ||
345 | |||
346 | |||
347 | /** | 343 | /** |
348 | * next_rts - find a real-time timestamp AROUND an FTRACE time | 344 | * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp. |
349 | * @ginfo: Current state of the graph | ||
350 | * @cpu: CPU to search | ||
351 | * @ft_target: FTRACE time to seek towards | ||
352 | * | ||
353 | * Returns the RT time of a record CLOSELY BEFORE @ft_time. | ||
354 | */ | ||
355 | unsigned long long | ||
356 | next_rts(struct graph_info *ginfo, int cpu, unsigned long long ft_target) | ||
357 | { | ||
358 | struct record *record; | ||
359 | unsigned long long ts = 0ULL; | ||
360 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, ft_target); | ||
361 | record = tracecmd_read_data(ginfo->handle, cpu); | ||
362 | if (record) { | ||
363 | ts = get_rts(ginfo, record); | ||
364 | free_record(record); | ||
365 | return ts; | ||
366 | } else | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp | ||
372 | * @ginfo: Current state o the graph | ||
373 | * @cpu: The CPU to seek | 345 | * @cpu: The CPU to seek |
374 | * @rt_target: RT time to seek towards | 346 | * @rt_target: RT time to seek towards |
375 | * | 347 | * |
376 | * This seeks to a real-time timestamp, not the default ftrace timestamps. | 348 | * This seeks to a real-time timestamp, not the default ftrace timestamps. |
377 | * The @cpu seek location will be placed before the given time, but will | 349 | * The @cpu seek location will be placed on the last record whose timestamp |
378 | * not necessarily be placed _right_ before the time. | 350 | * is less than @rt_target. |
379 | */ | 351 | */ |
380 | unsigned long long | 352 | long long correction = 0; |
381 | set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu) | 353 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, |
354 | unsigned long long rt_target, int cpu) | ||
382 | { | 355 | { |
383 | struct record *record; | 356 | struct record *record, *last_record; |
384 | unsigned long long last_rts, rts, seek_time, last_seek; | 357 | unsigned long long rts, seek_time; |
385 | long long diff; | 358 | long long next_diff; |
386 | 359 | ||
387 | rts = next_rts(ginfo, cpu, rt_target); | 360 | seek_time = rt_target + correction; |
388 | diff = rt_target - rts; | 361 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); |
389 | 362 | ||
390 | /* "Guess" a new target based on difference */ | 363 | last_record = tracecmd_read_data(ginfo->handle, cpu); |
391 | seek_time = rt_target + diff; | 364 | rts = get_rts(ginfo, last_record); |
392 | rts = next_rts(ginfo, cpu, seek_time); | 365 | if (rts < rt_target) { |
393 | diff = rt_target - rts; | 366 | while ((record = tracecmd_read_data(ginfo->handle, cpu))) { |
394 | 367 | if (get_rts(ginfo, record) >= rt_target) { | |
395 | /* Zero in in 1.5x the difference increments */ | 368 | free_record(record); |
396 | if (rts && diff > 0) { | 369 | break; |
397 | /* rts rt_target | real-time time | 370 | } |
398 | * seek ? | trace-cmd time | 371 | free_record(last_record); |
399 | * ---|---->>----|-------- | 372 | last_record = record; |
400 | */ | 373 | } |
401 | do { | 374 | } else if (rts > rt_target) { |
402 | last_seek = seek_time; | 375 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { |
403 | last_rts = rts; | 376 | if (get_rts(ginfo, record) <= rt_target) { |
404 | seek_time = seek_time + 1.5 * (rt_target - rts); | 377 | free_record(last_record); |
405 | rts = next_rts(ginfo, cpu, seek_time); | 378 | last_record = record; |
406 | } while (rts < rt_target && last_rts != rts); | 379 | break; |
407 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek); | 380 | } |
408 | seek_time = last_seek; | 381 | free_record(last_record); |
409 | } else if (rts && diff < 0) { | 382 | last_record = record; |
410 | /* rt_target rts | real-time time | 383 | } |
411 | * ? seek | trace-cmd time | ||
412 | * ---|----<<----|-------- | ||
413 | */ | ||
414 | do { | ||
415 | seek_time = seek_time - 1.5 * (rts - rt_target); | ||
416 | last_rts = rts; | ||
417 | rts = next_rts(ginfo, cpu, seek_time); | ||
418 | } while (rts > rt_target && rts != last_rts); | ||
419 | } | 384 | } |
420 | 385 | ||
421 | /* Get to first record at or after time */ | 386 | if (last_record) { |
422 | while ((record = tracecmd_read_data(ginfo->handle, cpu))) { | 387 | next_diff = (last_record->ts - rt_target); |
423 | if (get_rts(ginfo, record) >= rt_target) | 388 | if (correction) |
424 | break; | 389 | correction = correction *3/ 4 + (next_diff) / 4; |
425 | free_record(record); | 390 | else |
391 | correction = next_diff; | ||
392 | tracecmd_set_cursor(ginfo->handle, cpu, last_record->offset); | ||
393 | free_record(last_record); | ||
426 | } | 394 | } |
427 | if (record) { | 395 | |
428 | tracecmd_set_cursor(ginfo->handle, cpu, record->offset); | ||
429 | free_record(record); | ||
430 | } else | ||
431 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); | ||
432 | return rts; | 396 | return rts; |
433 | } | 397 | } |
434 | 398 | ||
435 | /** | 399 | /** |
436 | * set_cpus_to_time - seek all cpus to real-time @rt_target | 400 | * set_cpus_to_time - seek all cpus to real-time @rt_target. |
437 | */ | 401 | */ |
438 | unsigned long long set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) | 402 | unsigned long long set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) |
439 | { | 403 | { |
@@ -491,6 +455,9 @@ int is_task_running(struct graph_info *ginfo, | |||
491 | return running; | 455 | return running; |
492 | } | 456 | } |
493 | 457 | ||
458 | /** | ||
459 | * iterate - pass records in real-time timestamp order to @cb. | ||
460 | */ | ||
494 | void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | 461 | void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) |
495 | { | 462 | { |
496 | int proceed, cpu; | 463 | int proceed, cpu; |
@@ -502,47 +469,48 @@ void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | |||
502 | memset(nodes, 0, sizeof(*nodes) * ginfo->cpus); | 469 | memset(nodes, 0, sizeof(*nodes) * ginfo->cpus); |
503 | memset(&list, 0, sizeof(list)); | 470 | memset(&list, 0, sizeof(list)); |
504 | 471 | ||
505 | /* Maintains a list of the next record on each cpu, sorted by | 472 | /* Start with the first record on each CPU */ |
506 | * timestamp. Start with the first record on each cpu. | ||
507 | */ | ||
508 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | 473 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { |
509 | next = tracecmd_peek_data(ginfo->handle, cpu); | 474 | next = tracecmd_peek_data(ginfo->handle, cpu); |
510 | if (next) { | 475 | if (next) { |
511 | if (reverse) { | 476 | if (reverse) { |
477 | /* Reading backwards is clumsy...*/ | ||
512 | prev = next; | 478 | prev = next; |
513 | next = tracecmd_read_prev(ginfo->handle, prev); | 479 | next = tracecmd_read_prev(ginfo->handle, prev); |
514 | if (prev != next && prev->data) { | 480 | if (prev != next && prev->data) |
515 | free_record(prev); | 481 | free_record(prev); |
516 | } | 482 | } else { |
483 | next = tracecmd_read_data(ginfo->handle, cpu); | ||
517 | } | 484 | } |
518 | insert_record(ginfo, &list, next, &nodes[cpu], reverse); | 485 | insert_record(ginfo, &list, next, &nodes[cpu], reverse); |
519 | } | 486 | } |
520 | } | 487 | } |
521 | 488 | ||
522 | /* Read sequentially from all cpus */ | 489 | /* Read record with the next timestamp until the callback is finished |
490 | * consuming data | ||
491 | */ | ||
523 | while (pop_record(ginfo, &list, &node)) { | 492 | while (pop_record(ginfo, &list, &node)) { |
524 | next = node->record; | 493 | next = node->record; |
525 | 494 | ||
495 | /* Pass records into callback */ | ||
526 | proceed = cb(ginfo, next, data); | 496 | proceed = cb(ginfo, next, data); |
527 | |||
528 | if (!proceed) { | 497 | if (!proceed) { |
529 | free_record(next); | 498 | free_record(next); |
530 | break; | 499 | break; |
531 | } | 500 | } |
532 | 501 | ||
502 | /* Replace this record with the next record from the same CPU */ | ||
533 | prev = next; | 503 | prev = next; |
534 | 504 | if (!reverse) | |
535 | if (!reverse) { | ||
536 | next = tracecmd_read_data(ginfo->handle, next->cpu); | 505 | next = tracecmd_read_data(ginfo->handle, next->cpu); |
537 | } else { | 506 | else |
538 | next = tracecmd_read_prev(ginfo->handle, next); | 507 | next = tracecmd_read_prev(ginfo->handle, next); |
539 | } | ||
540 | |||
541 | free_record(prev); | 508 | free_record(prev); |
542 | 509 | if (prev != next) | |
543 | insert_record(ginfo, &list, next, node, reverse); | 510 | insert_record(ginfo, &list, next, node, reverse); |
544 | } | 511 | } |
545 | 512 | ||
513 | /* Free unused records */ | ||
546 | while (pop_record(ginfo, &list, &node)) { | 514 | while (pop_record(ginfo, &list, &node)) { |
547 | free_record(node->record); | 515 | free_record(node->record); |
548 | } | 516 | } |
@@ -550,7 +518,7 @@ void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | |||
550 | 518 | ||
551 | 519 | ||
552 | /** | 520 | /** |
553 | * Find the information for the last release of @match_tid on @cpu before @time. | 521 | * get_previous_release - return stats for the latest release of @match_tid |
554 | * | 522 | * |
555 | * This method will NOT re-seek the CPUs near time. The caller must have placed | 523 | * This method will NOT re-seek the CPUs near time. The caller must have placed |
556 | * the CPUs near the the CPUs themselves. | 524 | * the CPUs near the the CPUs themselves. |
@@ -68,7 +68,7 @@ find_rt_display_record(struct graph_info *ginfo, | |||
68 | return __find_rt_record(ginfo, rt, time, 1, 0); | 68 | return __find_rt_record(ginfo, rt, time, 1, 0); |
69 | } | 69 | } |
70 | 70 | ||
71 | unsigned long long next_rts(struct graph_info *ginfo, int cpu, | 71 | long long next_rts(struct graph_info *ginfo, int cpu, |
72 | unsigned long long ft_target); | 72 | unsigned long long ft_target); |
73 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, | 73 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, |
74 | unsigned long long rt_target, int cpu); | 74 | unsigned long long rt_target, int cpu); |
diff --git a/trace-dialog.c b/trace-dialog.c index 4e1d6e2..00ab269 100644 --- a/trace-dialog.c +++ b/trace-dialog.c | |||
@@ -183,7 +183,6 @@ void warning(const char *fmt, ...) | |||
183 | { | 183 | { |
184 | GString *str; | 184 | GString *str; |
185 | va_list ap; | 185 | va_list ap; |
186 | int err; | ||
187 | 186 | ||
188 | if (alt_warning) { | 187 | if (alt_warning) { |
189 | va_start(ap, fmt); | 188 | va_start(ap, fmt); |
@@ -199,7 +198,6 @@ void warning(const char *fmt, ...) | |||
199 | return; | 198 | return; |
200 | } | 199 | } |
201 | 200 | ||
202 | err = errno; | ||
203 | errno = 0; | 201 | errno = 0; |
204 | 202 | ||
205 | str = g_string_new(""); | 203 | str = g_string_new(""); |
diff --git a/trace-graph.c b/trace-graph.c index 69f5069..0aa8137 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
@@ -1852,14 +1852,16 @@ static void draw_plot(struct graph_info *ginfo, struct graph_plot *plot, | |||
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | /* | 1854 | /* |
1855 | * TODO: this method needs refactoring and splitting | 1855 | * TODO: this method needs refactoring and splitting. |
1856 | * Containers currently aren't using hashing, which can significantly affect | ||
1857 | * performance if enough containers are being rendered. | ||
1856 | */ | 1858 | */ |
1857 | static void draw_hashed_plots(struct graph_info *ginfo) | 1859 | static void draw_hashed_plots(struct graph_info *ginfo) |
1858 | { | 1860 | { |
1859 | gint cpu, pid, clean; | 1861 | gint cpu, pid, clean; |
1860 | struct record *record; | 1862 | struct record *record; |
1861 | struct plot_hash *hash; | ||
1862 | struct plot_list *list; | 1863 | struct plot_list *list; |
1864 | struct plot_hash *hash; | ||
1863 | unsigned long long max_time, min_time; | 1865 | unsigned long long max_time, min_time; |
1864 | gdouble start, duration; | 1866 | gdouble start, duration; |
1865 | 1867 | ||
@@ -1940,19 +1942,19 @@ static void draw_hashed_plots(struct graph_info *ginfo) | |||
1940 | } | 1942 | } |
1941 | 1943 | ||
1942 | 1944 | ||
1943 | /* hash = trace_graph_plot_find_cpu(ginfo, cpu); */ | 1945 | hash = trace_graph_plot_find_cpu(ginfo, cpu); |
1944 | /* if (hash) { */ | 1946 | if (hash) { |
1945 | /* for (list = hash->plots; list; list = list->next) { */ | 1947 | for (list = hash->plots; list; list = list->next) { |
1946 | /* draw_plot(ginfo, list->plot, record); */ | 1948 | draw_plot(ginfo, list->plot, record); |
1947 | /* } */ | 1949 | } |
1948 | /* } */ | 1950 | } |
1949 | /* pid = pevent_data_pid(ginfo->pevent, record); */ | 1951 | pid = pevent_data_pid(ginfo->pevent, record); |
1950 | /* hash = trace_graph_plot_find_task(ginfo, pid); */ | 1952 | hash = trace_graph_plot_find_task(ginfo, pid); |
1951 | /* if (hash) { */ | 1953 | if (hash) { |
1952 | /* for (list = hash->plots; list; list = list->next) { */ | 1954 | for (list = hash->plots; list; list = list->next) { |
1953 | /* draw_plot(ginfo, list->plot, record); */ | 1955 | draw_plot(ginfo, list->plot, record); |
1954 | /* } */ | 1956 | } |
1955 | /* } */ | 1957 | } |
1956 | for (list = ginfo->all_recs; list; list = list->next) { | 1958 | for (list = ginfo->all_recs; list; list = list->next) { |
1957 | /* TODO: hacky assumption that everything else can be | 1959 | /* TODO: hacky assumption that everything else can be |
1958 | * reached via previous hashes | 1960 | * reached via previous hashes |
@@ -1960,10 +1962,10 @@ static void draw_hashed_plots(struct graph_info *ginfo) | |||
1960 | * added with arbitrary numbers, and a pevent_other_id | 1962 | * added with arbitrary numbers, and a pevent_other_id |
1961 | * which uses id ranges x < . < y to parse cids or lids | 1963 | * which uses id ranges x < . < y to parse cids or lids |
1962 | */ | 1964 | */ |
1963 | /* if (list->plot->type == PLOT_TYPE_SERVER_TASK || */ | 1965 | if (list->plot->type == PLOT_TYPE_SERVER_TASK || |
1964 | /* list->plot->type == PLOT_TYPE_SERVER_CPU) { */ | 1966 | list->plot->type == PLOT_TYPE_SERVER_CPU) { |
1965 | draw_plot(ginfo, list->plot, record); | 1967 | draw_plot(ginfo, list->plot, record); |
1966 | /* } */ | 1968 | } |
1967 | } | 1969 | } |
1968 | free_record(record); | 1970 | free_record(record); |
1969 | } | 1971 | } |