Skip to content

Commit 285dcb7

Browse files
author
Daniel Bristot de Oliveira
committed
rtla/timerlat: Add a summary for top mode
While the per-cpu values are the results to take into consideration, the overall system values are also useful. Add a summary at the bottom of rtla timerlat top showing the overall results. For instance: Timer Latency 0 00:00:10 | IRQ Timer Latency (us) | Thread Timer Latency (us) CPU COUNT | cur min avg max | cur min avg max 0 #10003 | 113 19 150 441 | 134 35 170 459 1 #10003 | 63 8 99 462 | 84 15 119 481 2 #10003 | 3 2 89 396 | 21 8 108 414 3 #10002 | 206 11 210 394 | 223 21 228 415 ---------------|----------------------------------------|--------------------------------------- ALL #40011 e0 | 2 137 462 | 8 156 481 Link: https://lkml.kernel.org/r/5eb510d6faeb4ce745e09395196752df75a2dd1a.1713968967.git.bristot@kernel.org Cc: Jonathan Corbet <[email protected]> Suggested-by: Juri Lelli <[email protected]> Signed-off-by: Daniel Bristot de Oliveira <[email protected]>
1 parent f5c0cda commit 285dcb7

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

tools/tracing/rtla/src/timerlat_top.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,37 @@ static struct timerlat_top_data *timerlat_alloc_top(int nr_cpus)
119119
return NULL;
120120
}
121121

122+
static void
123+
timerlat_top_reset_sum(struct timerlat_top_cpu *summary)
124+
{
125+
memset(summary, 0, sizeof(*summary));
126+
summary->min_irq = ~0;
127+
summary->min_thread = ~0;
128+
summary->min_user = ~0;
129+
}
130+
131+
static void
132+
timerlat_top_update_sum(struct osnoise_tool *tool, int cpu, struct timerlat_top_cpu *sum)
133+
{
134+
struct timerlat_top_data *data = tool->data;
135+
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
136+
137+
sum->irq_count += cpu_data->irq_count;
138+
update_min(&sum->min_irq, &cpu_data->min_irq);
139+
update_sum(&sum->sum_irq, &cpu_data->sum_irq);
140+
update_max(&sum->max_irq, &cpu_data->max_irq);
141+
142+
sum->thread_count += cpu_data->thread_count;
143+
update_min(&sum->min_thread, &cpu_data->min_thread);
144+
update_sum(&sum->sum_thread, &cpu_data->sum_thread);
145+
update_max(&sum->max_thread, &cpu_data->max_thread);
146+
147+
sum->user_count += cpu_data->user_count;
148+
update_min(&sum->min_user, &cpu_data->min_user);
149+
update_sum(&sum->sum_user, &cpu_data->sum_user);
150+
update_max(&sum->max_user, &cpu_data->max_user);
151+
}
152+
122153
/*
123154
* timerlat_hist_update - record a new timerlat occurent on cpu, updating data
124155
*/
@@ -285,6 +316,77 @@ static void timerlat_top_print(struct osnoise_tool *top, int cpu)
285316
}
286317
}
287318

319+
/*
320+
* timerlat_top_print_sum - prints the summary output
321+
*/
322+
static void
323+
timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summary)
324+
{
325+
const char *split = "----------------------------------------";
326+
struct timerlat_top_params *params = top->params;
327+
unsigned long long count = summary->irq_count;
328+
int divisor = params->output_divisor;
329+
struct trace_seq *s = top->trace.seq;
330+
int e = 0;
331+
332+
if (divisor == 0)
333+
return;
334+
335+
/*
336+
* Skip if no data is available: is this cpu offline?
337+
*/
338+
if (!summary->irq_count && !summary->thread_count)
339+
return;
340+
341+
while (count > 999999) {
342+
e++;
343+
count /= 10;
344+
}
345+
346+
trace_seq_printf(s, "%.*s|%.*s|%.*s", 15, split, 40, split, 39, split);
347+
if (params->user_top)
348+
trace_seq_printf(s, "-|%.*s", 39, split);
349+
trace_seq_printf(s, "\n");
350+
351+
trace_seq_printf(s, "ALL #%-6llu e%d |", count, e);
352+
353+
if (!summary->irq_count) {
354+
trace_seq_printf(s, " %s %s %s |", no_value, no_value, no_value);
355+
} else {
356+
trace_seq_printf(s, " ");
357+
trace_seq_printf(s, "%9llu ", summary->min_irq / params->output_divisor);
358+
trace_seq_printf(s, "%9llu ", (summary->sum_irq / summary->irq_count) / divisor);
359+
trace_seq_printf(s, "%9llu |", summary->max_irq / divisor);
360+
}
361+
362+
if (!summary->thread_count) {
363+
trace_seq_printf(s, "%s %s %s %s", no_value, no_value, no_value, no_value);
364+
} else {
365+
trace_seq_printf(s, " ");
366+
trace_seq_printf(s, "%9llu ", summary->min_thread / divisor);
367+
trace_seq_printf(s, "%9llu ",
368+
(summary->sum_thread / summary->thread_count) / divisor);
369+
trace_seq_printf(s, "%9llu", summary->max_thread / divisor);
370+
}
371+
372+
if (!params->user_top) {
373+
trace_seq_printf(s, "\n");
374+
return;
375+
}
376+
377+
trace_seq_printf(s, " |");
378+
379+
if (!summary->user_count) {
380+
trace_seq_printf(s, " %s %s %s |", no_value, no_value, no_value);
381+
} else {
382+
trace_seq_printf(s, " ");
383+
trace_seq_printf(s, "%9llu ", summary->min_user / divisor);
384+
trace_seq_printf(s, "%9llu ",
385+
(summary->sum_user / summary->user_count) / divisor);
386+
trace_seq_printf(s, "%9llu\n", summary->max_user / divisor);
387+
}
388+
}
389+
288390
/*
289391
* clear_terminal - clears the output terminal
290392
*/
@@ -301,6 +403,7 @@ static void
301403
timerlat_print_stats(struct timerlat_top_params *params, struct osnoise_tool *top)
302404
{
303405
struct trace_instance *trace = &top->trace;
406+
struct timerlat_top_cpu summary;
304407
static int nr_cpus = -1;
305408
int i;
306409

@@ -313,14 +416,19 @@ timerlat_print_stats(struct timerlat_top_params *params, struct osnoise_tool *to
313416
if (!params->quiet)
314417
clear_terminal(trace->seq);
315418

419+
timerlat_top_reset_sum(&summary);
420+
316421
timerlat_top_header(params, top);
317422

318423
for (i = 0; i < nr_cpus; i++) {
319424
if (params->cpus && !CPU_ISSET(i, &params->monitored_cpus))
320425
continue;
321426
timerlat_top_print(top, i);
427+
timerlat_top_update_sum(top, i, &summary);
322428
}
323429

430+
timerlat_top_print_sum(top, &summary);
431+
324432
trace_seq_do_printf(trace->seq);
325433
trace_seq_reset(trace->seq);
326434
}

0 commit comments

Comments
 (0)