rtla: Add the --warm-up option

On many cases, the results right after the startup are different
from the rest of the execution, biasing the results. For example,
on osnoise, the scheduler might take some time to adapt to the new
busy-loop workload.

Add the --warm-up <seconds> option, adding a warm-up phase (in
seconds) where the workload is set, but the results are discarded.

Link: https://lkml.kernel.org/r/e682d5ce5af90f123bd13220f63d5c3d118a92be.1713968967.git.bristot@kernel.org

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Juri Lelli <juri.lelli@redhat.com>
Signed-off-by: default avatarDaniel Bristot de Oliveira <bristot@kernel.org>
parent 1462501c
......@@ -50,6 +50,10 @@
Set a *cgroup* to the tracer's threads. If the **-C** option is passed without arguments, the tracer's thread will inherit **rtla**'s *cgroup*. Otherwise, the threads will be placed on the *cgroup* passed to the option.
**--warm-up** *s*
After starting the workload, let it run for *s* seconds before starting collecting the data, allowing the system to warm-up. Statistical data generated during warm-up is discarded.
**-h**, **--help**
Print help menu.
......@@ -36,13 +36,13 @@ struct osnoise_hist_params {
cpu_set_t hk_cpu_set;
struct sched_attr sched_param;
struct trace_events *events;
char no_header;
char no_summary;
char no_index;
char with_zeros;
int bucket_size;
int entries;
int warmup;
};
struct osnoise_hist_cpu {
......@@ -438,7 +438,7 @@ static void osnoise_hist_usage(char *usage)
" usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
" [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
" [-c cpu-list] [-H cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\",
" [--no-index] [--with-zeros] [-C[=cgroup_name]]",
" [--no-index] [--with-zeros] [-C[=cgroup_name]] [--warm-up]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
......@@ -468,6 +468,7 @@ static void osnoise_hist_usage(char *usage)
" f:prio - use SCHED_FIFO with prio",
" d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
" in nanoseconds",
" --warm-up: let the workload run for s seconds before collecting data",
NULL,
};
......@@ -531,13 +532,14 @@ static struct osnoise_hist_params
{"with-zeros", no_argument, 0, '3'},
{"trigger", required_argument, 0, '4'},
{"filter", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:",
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:",
long_options, &option_index);
/* detect the end of the options. */
......@@ -680,6 +682,9 @@ static struct osnoise_hist_params
osnoise_hist_usage("--filter requires a previous -e\n");
}
break;
case '6':
params->warmup = get_llong_from_str(optarg);
break;
default:
osnoise_hist_usage("Invalid option");
}
......@@ -899,6 +904,25 @@ int osnoise_hist_main(int argc, char *argv[])
trace_instance_start(&record->trace);
trace_instance_start(trace);
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
if (stop_tracing)
goto out_hist;
/*
* Clean up the buffer. The osnoise workload do not run
* with tracing off to avoid creating a performance penalty
* when not needed.
*/
retval = tracefs_instance_file_write(trace->inst, "trace", "");
if (retval < 0) {
debug_msg("Error cleaning up the buffer");
goto out_hist;
}
}
tool->start_time = time(NULL);
osnoise_hist_set_signals(params);
......
......@@ -40,6 +40,7 @@ struct osnoise_top_params {
int set_sched;
int cgroup;
int hk_cpus;
int warmup;
cpu_set_t hk_cpu_set;
struct sched_attr sched_param;
struct trace_events *events;
......@@ -282,7 +283,7 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
static const char * const msg[] = {
" [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
" [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
" [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]]",
" [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]] [--warm-up s]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
......@@ -307,6 +308,7 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
" f:prio - use SCHED_FIFO with prio",
" d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
" in nanoseconds",
" --warm-up s: let the workload run for s seconds before collecting data",
NULL,
};
......@@ -381,13 +383,14 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
{"trace", optional_argument, 0, 't'},
{"trigger", required_argument, 0, '0'},
{"filter", required_argument, 0, '1'},
{"warm-up", required_argument, 0, '2'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:",
c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:",
long_options, &option_index);
/* Detect the end of the options. */
......@@ -511,6 +514,9 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "--filter requires a previous -e\n");
}
break;
case '2':
params->warmup = get_llong_from_str(optarg);
break;
default:
osnoise_top_usage(params, "Invalid option");
}
......@@ -732,6 +738,25 @@ int osnoise_top_main(int argc, char **argv)
trace_instance_start(&record->trace);
trace_instance_start(trace);
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
if (stop_tracing)
goto out_top;
/*
* Clean up the buffer. The osnoise workload do not run
* with tracing off to avoid creating a performance penalty
* when not needed.
*/
retval = tracefs_instance_file_write(trace->inst, "trace", "");
if (retval < 0) {
debug_msg("Error cleaning up the buffer");
goto out_top;
}
}
tool->start_time = time(NULL);
osnoise_top_set_signals(params);
......
......@@ -52,6 +52,7 @@ struct timerlat_hist_params {
char with_zeros;
int bucket_size;
int entries;
int warmup;
};
struct timerlat_hist_cpu {
......@@ -628,6 +629,7 @@ static void timerlat_hist_usage(char *usage)
" [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\",
" [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
" [--no-index] [--with-zeros] [--dma-latency us] [-C[=cgroup_name]] [--no-aa] [--dump-task] [-u]",
" [--warm-up s]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
......@@ -664,6 +666,7 @@ static void timerlat_hist_usage(char *usage)
" in nanoseconds",
" -u/--user-threads: use rtla user-space threads instead of in-kernel timerlat threads",
" -U/--user-load: enable timerlat for user-defined user-space workload",
" --warm-up s: let the workload run for s seconds before collecting data",
NULL,
};
......@@ -738,13 +741,14 @@ static struct timerlat_hist_params
{"dma-latency", required_argument, 0, '8'},
{"no-aa", no_argument, 0, '9'},
{"dump-task", no_argument, 0, '\1'},
{"warm-up", required_argument, 0, '\2'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:np:P:s:t::T:uU0123456:7:8:9\1",
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:np:P:s:t::T:uU0123456:7:8:9\1\2:",
long_options, &option_index);
/* detect the end of the options. */
......@@ -913,6 +917,9 @@ static struct timerlat_hist_params
case '\1':
params->dump_tasks = 1;
break;
case '\2':
params->warmup = get_llong_from_str(optarg);
break;
default:
timerlat_hist_usage("Invalid option");
}
......@@ -1167,22 +1174,6 @@ int timerlat_hist_main(int argc, char *argv[])
}
}
/*
* Start the tracers here, after having set all instances.
*
* Let the trace instance start first for the case of hitting a stop
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
if (params->trace_output)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
trace_instance_start(trace);
tool->start_time = time(NULL);
timerlat_hist_set_signals(params);
if (params->user_workload) {
/* rtla asked to stop */
params_u.should_run = 1;
......@@ -1202,6 +1193,29 @@ int timerlat_hist_main(int argc, char *argv[])
err_msg("Error creating timerlat user-space threads\n");
}
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
if (stop_tracing)
goto out_hist;
}
/*
* Start the tracers here, after having set all instances.
*
* Let the trace instance start first for the case of hitting a stop
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
if (params->trace_output)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
trace_instance_start(trace);
tool->start_time = time(NULL);
timerlat_hist_set_signals(params);
while (!stop_tracing) {
sleep(params->sleep_time);
......@@ -1227,6 +1241,7 @@ int timerlat_hist_main(int argc, char *argv[])
}
}
}
if (params->user_workload && !params_u.stopped_running) {
params_u.should_run = 0;
sleep(1);
......
......@@ -45,6 +45,7 @@ struct timerlat_top_params {
int user_top;
int user_workload;
int pretty_output;
int warmup;
cpu_set_t hk_cpu_set;
struct sched_attr sched_param;
struct trace_events *events;
......@@ -444,7 +445,7 @@ 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] [-H cpu-list]\\",
" [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u]",
" [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u] [--warm-up s]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
......@@ -475,6 +476,7 @@ static void timerlat_top_usage(char *usage)
" in nanoseconds",
" -u/--user-threads: use rtla user-space threads instead of in-kernel timerlat threads",
" -U/--user-load: enable timerlat for user-defined user-space workload",
" --warm-up s: let the workload run for s seconds before collecting data",
NULL,
};
......@@ -541,13 +543,14 @@ static struct timerlat_top_params
{"no-aa", no_argument, 0, '3'},
{"dump-tasks", no_argument, 0, '4'},
{"aa-only", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::d:De:hH:i:np:P:qs:t::T:uU0:1:2:345:",
c = getopt_long(argc, argv, "a:c:C::d:De:hH:i:np:P:qs:t::T:uU0:1:2:345:6:",
long_options, &option_index);
/* detect the end of the options. */
......@@ -704,6 +707,9 @@ static struct timerlat_top_params
case '4':
params->dump_tasks = 1;
break;
case '6':
params->warmup = get_llong_from_str(optarg);
break;
default:
timerlat_top_usage("Invalid option");
}
......@@ -971,22 +977,6 @@ int timerlat_top_main(int argc, char *argv[])
}
}
/*
* Start the tracers here, after having set all instances.
*
* Let the trace instance start first for the case of hitting a stop
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
if (params->trace_output)
trace_instance_start(&record->trace);
if (!params->no_aa && aa != top)
trace_instance_start(&aa->trace);
trace_instance_start(trace);
top->start_time = time(NULL);
timerlat_top_set_signals(params);
if (params->user_workload) {
/* rtla asked to stop */
params_u.should_run = 1;
......@@ -1006,6 +996,27 @@ int timerlat_top_main(int argc, char *argv[])
err_msg("Error creating timerlat user-space threads\n");
}
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
}
/*
* Start the tracers here, after having set all instances.
*
* Let the trace instance start first for the case of hitting a stop
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
if (params->trace_output)
trace_instance_start(&record->trace);
if (!params->no_aa && aa != top)
trace_instance_start(&aa->trace);
trace_instance_start(trace);
top->start_time = time(NULL);
timerlat_top_set_signals(params);
while (!stop_tracing) {
sleep(params->sleep_time);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment