rtla/rtla-timerlat-Add-auto-analysis-only-option.patch
John Kacur 6bdff9a0a5 Add rtla timerlat auto analysis
Resolves: rhbz#2175292
jiraProject == RHELPLAN-150657

Signed-off-by: John Kacur <jkacur@redhat.com>
2023-07-14 15:48:27 -04:00

165 lines
5.7 KiB
Diff

From 9fa48a2477de747b644c778a1e35d679cabcd917 Mon Sep 17 00:00:00 2001
From: Daniel Bristot de Oliveira <bristot@kernel.org>
Date: Wed, 29 Mar 2023 18:23:32 +0200
Subject: [PATCH 7/8] rtla/timerlat: Add auto-analysis only option
Parsing and formating timerlat data might consume a reasonable
amount of CPU time on very large systems, or when timerlat
has a too short period.
Add an option to run timerlat with auto-analysis enabled while
skipping the statistics parsing. In this mode, rtla timerlat
periodically checks if the tracing is on, going to sleep waiting
for the stop tracing condition to stop tracing, or for the
tracing session to finish.
If the stop tracing condition is hit, the tool prints the auto
analysis. Otherwise, the tool prints the max observed latency and
exit. The max observed latency is captured via tracing_max_latency.
Link: https://lore.kernel.org/linux-trace-devel/4dc514d1d5dc353c537a466a9b5af44c266b6da2.1680106912.git.bristot@kernel.org
Cc: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
src/timerlat_top.c | 49 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/src/timerlat_top.c b/src/timerlat_top.c
index eea5b3357e27..92c658c64f28 100644
--- a/src/timerlat_top.c
+++ b/src/timerlat_top.c
@@ -33,6 +33,7 @@ struct timerlat_top_params {
int set_sched;
int dma_latency;
int no_aa;
+ int aa_only;
int dump_tasks;
struct sched_attr sched_param;
struct trace_events *events;
@@ -142,10 +143,12 @@ timerlat_top_handler(struct trace_seq *s, struct tep_record *record,
top = container_of(trace, struct osnoise_tool, trace);
params = top->params;
- tep_get_field_val(s, event, "context", record, &thread, 1);
- tep_get_field_val(s, event, "timer_latency", record, &latency, 1);
+ if (!params->aa_only) {
+ tep_get_field_val(s, event, "context", record, &thread, 1);
+ tep_get_field_val(s, event, "timer_latency", record, &latency, 1);
- timerlat_top_update(top, cpu, thread, latency);
+ timerlat_top_update(top, cpu, thread, latency);
+ }
if (!params->no_aa)
timerlat_aa_handler(s, record, event, context);
@@ -250,6 +253,9 @@ timerlat_print_stats(struct timerlat_top_params *params, struct osnoise_tool *to
static int nr_cpus = -1;
int i;
+ if (params->aa_only)
+ return;
+
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
@@ -279,10 +285,11 @@ static void timerlat_top_usage(char *usage)
"",
" usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\",
" [[-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
- " [-P priority] [--dma-latency us]",
+ " [-P priority] [--dma-latency us] [--aa-only us]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
+ " --aa-only us: stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)",
" -p/--period us: timerlat period in us",
" -i/--irq us: stop trace if the irq latency is higher than the argument in us",
" -T/--thread us: stop trace if the thread latency is higher than the argument in us",
@@ -362,13 +369,14 @@ static struct timerlat_top_params
{"dma-latency", required_argument, 0, '2'},
{"no-aa", no_argument, 0, '3'},
{"dump-tasks", no_argument, 0, '4'},
+ {"aa-only", required_argument, 0, '5'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
- c = getopt_long(argc, argv, "a:c:d:De:hi:np:P:qs:t::T:0:1:2:34",
+ c = getopt_long(argc, argv, "a:c:d:De:hi:np:P:qs:t::T:0:1:2:345:",
long_options, &option_index);
/* detect the end of the options. */
@@ -389,6 +397,20 @@ static struct timerlat_top_params
/* set trace */
params->trace_output = "timerlat_trace.txt";
break;
+ case '5':
+ /* it is here because it is similar to -a */
+ auto_thresh = get_llong_from_str(optarg);
+
+ /* set thread stop to auto_thresh */
+ params->stop_total_us = auto_thresh;
+ params->stop_us = auto_thresh;
+
+ /* get stack trace */
+ params->print_stack = auto_thresh;
+
+ /* set aa_only to avoid parsing the trace */
+ params->aa_only = 1;
+ break;
case 'c':
retval = parse_cpu_list(optarg, &params->monitored_cpus);
if (retval)
@@ -503,6 +525,9 @@ static struct timerlat_top_params
if (!params->stop_us && !params->stop_total_us)
params->no_aa = 1;
+ if (params->no_aa && params->aa_only)
+ timerlat_top_usage("--no-aa and --aa-only are mutually exclusive!");
+
return params;
}
@@ -634,6 +659,7 @@ int timerlat_top_main(int argc, char *argv[])
struct trace_instance *trace;
int dma_latency_fd = -1;
int return_value = 1;
+ char *max_lat;
int retval;
params = timerlat_top_parse_args(argc, argv);
@@ -700,6 +726,9 @@ int timerlat_top_main(int argc, char *argv[])
while (!stop_tracing) {
sleep(params->sleep_time);
+ if (params->aa_only && !trace_is_off(&top->trace, &record->trace))
+ continue;
+
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
NULL,
@@ -733,6 +762,16 @@ int timerlat_top_main(int argc, char *argv[])
printf(" Saving trace to %s\n", params->trace_output);
save_trace_to_file(record->trace.inst, params->trace_output);
}
+ } else if (params->aa_only) {
+ /*
+ * If the trace did not stop with --aa-only, at least print the
+ * max known latency.
+ */
+ max_lat = tracefs_instance_file_read(trace->inst, "tracing_max_latency", NULL);
+ if (max_lat) {
+ printf(" Max latency was %s\n", max_lat);
+ free(max_lat);
+ }
}
out_top:
--
2.40.1