Skip to content

Commit c66552b

Browse files
Daniel Bristot de Oliveirarostedt
authored andcommitted
rtla/timerlat: Give timerlat auto analysis its own instance
Currently, the auto-analysis is attached to the timerlat top instance. The idea was to avoid creating another instance just for that, so one instance could be reused. The drawback is that, by doing so, the auto-analysis run for the entire session, consuming CPU time. On my 24 box CPUs for timerlat with a 100 us period consumed 50 % with auto analysis, but only 16 % without. By creating an instance for auto-analysis, we can keep the processing stopped until a stop tracing condition is hit. Once it happens, timerlat auto-analysis can use its own trace instance to parse only the end of the trace. By doing so, auto-analysis stop consuming cpu time when it is not needed. If the --aa-only is passed, the timerlat top instance is reused for auto analysis. Link: https://lkml.kernel.org/r/346b7168c1bae552a415715ec6d23c129a43bdb7.1686066600.git.bristot@kernel.org Cc: William White <[email protected]> Cc: Jonathan Corbet <[email protected]> Tested-by: Juri Lelli <[email protected]> Signed-off-by: Daniel Bristot de Oliveira <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent c58a3f8 commit c66552b

File tree

3 files changed

+67
-21
lines changed

3 files changed

+67
-21
lines changed

tools/tracing/rtla/src/timerlat_aa.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "utils.h"
99
#include "osnoise.h"
1010
#include "timerlat.h"
11+
#include <unistd.h>
1112

1213
enum timelat_state {
1314
TIMERLAT_INIT = 0,
@@ -233,7 +234,7 @@ static int timerlat_aa_thread_latency(struct timerlat_aa_data *taa_data,
233234
*
234235
* Returns 0 on success, -1 otherwise.
235236
*/
236-
int timerlat_aa_handler(struct trace_seq *s, struct tep_record *record,
237+
static int timerlat_aa_handler(struct trace_seq *s, struct tep_record *record,
237238
struct tep_event *event, void *context)
238239
{
239240
struct timerlat_aa_context *taa_ctx = timerlat_aa_get_ctx();
@@ -665,6 +666,25 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
665666
ns_to_usf(total));
666667
}
667668

669+
static int timerlat_auto_analysis_collect_trace(struct timerlat_aa_context *taa_ctx)
670+
{
671+
struct trace_instance *trace = &taa_ctx->tool->trace;
672+
int retval;
673+
674+
retval = tracefs_iterate_raw_events(trace->tep,
675+
trace->inst,
676+
NULL,
677+
0,
678+
collect_registered_events,
679+
trace);
680+
if (retval < 0) {
681+
err_msg("Error iterating on events\n");
682+
return 0;
683+
}
684+
685+
return 1;
686+
}
687+
668688
/**
669689
* timerlat_auto_analysis - Analyze the collected data
670690
*/
@@ -677,6 +697,8 @@ void timerlat_auto_analysis(int irq_thresh, int thread_thresh)
677697
struct tep_handle *tep;
678698
int cpu;
679699

700+
timerlat_auto_analysis_collect_trace(taa_ctx);
701+
680702
/* bring stop tracing to the ns scale */
681703
irq_thresh = irq_thresh * 1000;
682704
thread_thresh = thread_thresh * 1000;
@@ -838,6 +860,10 @@ static int timerlat_aa_init_seqs(struct timerlat_aa_context *taa_ctx)
838860
*/
839861
static void timerlat_aa_unregister_events(struct osnoise_tool *tool, int dump_tasks)
840862
{
863+
864+
tep_unregister_event_handler(tool->trace.tep, -1, "ftrace", "timerlat",
865+
timerlat_aa_handler, tool);
866+
841867
tracefs_event_disable(tool->trace.inst, "osnoise", NULL);
842868

843869
tep_unregister_event_handler(tool->trace.tep, -1, "osnoise", "nmi_noise",
@@ -875,6 +901,10 @@ static int timerlat_aa_register_events(struct osnoise_tool *tool, int dump_tasks
875901
{
876902
int retval;
877903

904+
tep_register_event_handler(tool->trace.tep, -1, "ftrace", "timerlat",
905+
timerlat_aa_handler, tool);
906+
907+
878908
/*
879909
* register auto-analysis handlers.
880910
*/
@@ -955,8 +985,9 @@ void timerlat_aa_destroy(void)
955985
*
956986
* Returns 0 on success, -1 otherwise.
957987
*/
958-
int timerlat_aa_init(struct osnoise_tool *tool, int nr_cpus, int dump_tasks)
988+
int timerlat_aa_init(struct osnoise_tool *tool, int dump_tasks)
959989
{
990+
int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
960991
struct timerlat_aa_context *taa_ctx;
961992
int retval;
962993

tools/tracing/rtla/src/timerlat_aa.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
* Copyright (C) 2023 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]>
44
*/
55

6-
int timerlat_aa_init(struct osnoise_tool *tool, int nr_cpus, int dump_task);
6+
int timerlat_aa_init(struct osnoise_tool *tool, int dump_task);
77
void timerlat_aa_destroy(void);
88

9-
int timerlat_aa_handler(struct trace_seq *s, struct tep_record *record,
10-
struct tep_event *event, void *context);
11-
129
void timerlat_auto_analysis(int irq_thresh, int thread_thresh);

tools/tracing/rtla/src/timerlat_top.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,6 @@ timerlat_top_handler(struct trace_seq *s, struct tep_record *record,
156156
timerlat_top_update(top, cpu, thread, latency);
157157
}
158158

159-
if (!params->no_aa)
160-
timerlat_aa_handler(s, record, event, context);
161-
162159
return 0;
163160
}
164161

@@ -644,7 +641,6 @@ static struct osnoise_tool
644641
{
645642
struct osnoise_tool *top;
646643
int nr_cpus;
647-
int retval;
648644

649645
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
650646

@@ -661,16 +657,6 @@ static struct osnoise_tool
661657
tep_register_event_handler(top->trace.tep, -1, "ftrace", "timerlat",
662658
timerlat_top_handler, top);
663659

664-
/*
665-
* If no auto analysis, we are ready.
666-
*/
667-
if (params->no_aa)
668-
return top;
669-
670-
retval = timerlat_aa_init(top, nr_cpus, params->dump_tasks);
671-
if (retval)
672-
goto out_err;
673-
674660
return top;
675661

676662
out_err:
@@ -702,6 +688,7 @@ int timerlat_top_main(int argc, char *argv[])
702688
struct timerlat_top_params *params;
703689
struct osnoise_tool *record = NULL;
704690
struct osnoise_tool *top = NULL;
691+
struct osnoise_tool *aa = NULL;
705692
struct trace_instance *trace;
706693
int dma_latency_fd = -1;
707694
int return_value = 1;
@@ -774,6 +761,35 @@ int timerlat_top_main(int argc, char *argv[])
774761
trace_instance_start(&record->trace);
775762
}
776763

764+
if (!params->no_aa) {
765+
if (params->aa_only) {
766+
/* as top is not used for display, use it for aa */
767+
aa = top;
768+
} else {
769+
/* otherwise, a new instance is needed */
770+
aa = osnoise_init_tool("timerlat_aa");
771+
if (!aa)
772+
goto out_top;
773+
}
774+
775+
retval = timerlat_aa_init(aa, params->dump_tasks);
776+
if (retval) {
777+
err_msg("Failed to enable the auto analysis instance\n");
778+
goto out_top;
779+
}
780+
781+
/* if it is re-using the main instance, there is no need to start it */
782+
if (aa != top) {
783+
retval = enable_timerlat(&aa->trace);
784+
if (retval) {
785+
err_msg("Failed to enable timerlat tracer\n");
786+
goto out_top;
787+
}
788+
789+
trace_instance_start(&aa->trace);
790+
}
791+
}
792+
777793
top->start_time = time(NULL);
778794
timerlat_top_set_signals(params);
779795

@@ -829,13 +845,15 @@ int timerlat_top_main(int argc, char *argv[])
829845
}
830846

831847
out_top:
848+
timerlat_aa_destroy();
832849
if (dma_latency_fd >= 0)
833850
close(dma_latency_fd);
834851
trace_events_destroy(&record->trace, params->events);
835852
params->events = NULL;
836853
out_free:
837854
timerlat_free_top(top->data);
838-
timerlat_aa_destroy();
855+
if (aa && aa != top)
856+
osnoise_destroy_tool(aa);
839857
osnoise_destroy_tool(record);
840858
osnoise_destroy_tool(top);
841859
free(params);

0 commit comments

Comments
 (0)