Provide --threads option in perf record command line interface.
Threaded streaming mode mitigates profiling data losses and
resolves scalability issues of serial and asynchronous (--aio) trace
streaming modes on multicore server systems. The implementation is
based on the prototype [1], [2] and the most closely relates to mode 3)
"mode that creates thread for every monitored memory map".

Threaded streaming mode is available with Zstd compression/decompression
(--compression-level) and handling of external commands (--control).
AUX area tracing, related and derived modes like --snapshot or
--aux-sample are not enabled. --switch-output, --switch-output-event,
--switch-max-files and --timestamp-filename options are not enabled.
Threaded trace streaming is not enabled for pipe mode. Initial intent
to enable AUX area tracing faced the need to define some optimal way
to store index data at data directory thus left aside. --switch-output-*
and --timestamp-filename use cases are not yet clear for data directories.

Asynchronous (--aio) trace streaming and affinity (--affinity) modes
are mutually exclusive to the exposed threaded streaming mode.

[1] git clone https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git -b 
perf/record_threads
[2] https://lore.kernel.org/lkml/20180913125450.21342-1-jo...@kernel.org/

Suggested-by: Jiri Olsa <jo...@kernel.org>
Suggested-by: Namhyung Kim <namhy...@kernel.org>
Signed-off-by: Alexey Budankov <alexey.budan...@linux.intel.com>
---
 tools/perf/Documentation/perf-record.txt |  7 ++++
 tools/perf/builtin-record.c              | 45 +++++++++++++++++++++---
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index 768888b9326a..d8fa387da973 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -671,6 +671,13 @@ Example of bash shell script to enable and disable events 
during measurements:
  wait -n ${perf_pid}
  exit $?
 
+--threads::
+Write collected trace data into per-CPU trace files using parallel threads.
+List of monitored CPUs can be configured by a mask provided via --cpu option.
+Trace writing threads correspond one-to-one to mapped data buffers. Threads
+and buffers are affined to monitored CPUs and NUMA nodes according to system
+topology. Threaded trace streaming mode is mutually exclusive to asynchronous
+trace streaming (--aio) and affinity (--affinity) modes.
 
 SEE ALSO
 --------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 1d41e996a994..575b0b595081 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -780,6 +780,12 @@ static int record__auxtrace_init(struct record *rec)
 {
        int err;
 
+       if ((rec->opts.auxtrace_snapshot_opts || rec->opts.auxtrace_sample_opts)
+           && record__threads_enabled(rec)) {
+               pr_err("AUX area tracing options are not available in threaded 
streaming mode.\n");
+               return -EINVAL;
+       }
+
        if (!rec->itr) {
                rec->itr = auxtrace_record__init(rec->evlist, &err);
                if (err)
@@ -2008,6 +2014,11 @@ static int __cmd_record(struct record *rec, int argc, 
const char **argv)
                return PTR_ERR(session);
        }
 
+       if (record__threads_enabled(rec) && perf_data__is_pipe(&rec->data)) {
+               pr_err("Threaded trace streaming is not available in pipe 
mode.\n");
+               return -1;
+       }
+
        fd = perf_data__fd(data);
        rec->session = session;
 
@@ -2680,12 +2691,22 @@ static int switch_output_setup(struct record *rec)
         * --switch-output=signal, as we'll send a SIGUSR2 from the side band
         *  thread to its parent.
         */
-       if (rec->switch_output_event_set)
+       if (rec->switch_output_event_set) {
+               if (record__threads_enabled(rec)) {
+                       pr_warning("WARNING: --switch-output-event option is 
not available in threaded streaming mode.\n");
+                       return 0;
+               }
                goto do_signal;
+       }
 
        if (!s->set)
                return 0;
 
+       if (record__threads_enabled(rec)) {
+               pr_warning("WARNING: --switch-output option is not available in 
threaded streaming mode.\n");
+               return 0;
+       }
+
        if (!strcmp(s->str, "signal")) {
 do_signal:
                s->signal = true;
@@ -2964,8 +2985,8 @@ static struct option __record_options[] = {
                     "Set affinity mask of trace reading thread to NUMA node 
cpu mask or cpu of processed mmap buffer",
                     record__parse_affinity),
 #ifdef HAVE_ZSTD_SUPPORT
-       OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, 
&comp_level_default,
-                           "n", "Compressed records using specified level 
(default: 1 - fastest compression, 22 - greatest compression)",
+       OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, 
&comp_level_default, "n",
+                           "Compress records using specified level (default: 1 
- fastest compression, 22 - greatest compression)",
                            record__parse_comp_level),
 #endif
        OPT_CALLBACK(0, "max-size", &record.output_max_size,
@@ -2984,6 +3005,8 @@ static struct option __record_options[] = {
                     "\t\t\t  Optionally send control command completion 
('ack\\n') to ack-fd descriptor.\n"
                     "\t\t\t  Alternatively, ctl-fifo / ack-fifo will be opened 
and used as ctl-fd / ack-fd.",
                      parse_control_option),
+       OPT_BOOLEAN(0, "threads", &record.opts.threads,
+                   "write collected trace data into per-CPU trace files using 
parallel threads"),
        OPT_END()
 };
 
@@ -3046,8 +3069,17 @@ int cmd_record(int argc, const char **argv)
        if (rec->opts.kcore || record__threads_enabled(rec))
                rec->data.is_dir = true;
 
-       if (record__threads_enabled(rec))
+       if (record__threads_enabled(rec)) {
+               if (rec->opts.affinity != PERF_AFFINITY_SYS) {
+                       pr_err("--affinity option is mutually exclusive to 
threaded streaming mode.\n");
+                       goto out_opts;
+               }
                rec->opts.affinity = PERF_AFFINITY_CPU;
+               if (record__aio_enabled(rec)) {
+                       pr_err("Asynchronous streaming mode (--aio) is mutually 
exclusive to threaded streaming mode.\n");
+                       goto out_opts;
+               }
+       }
 
        if (rec->opts.comp_level != 0) {
                pr_debug("Compression enabled, disabling build id collection at 
the end of the session.\n");
@@ -3082,6 +3114,11 @@ int cmd_record(int argc, const char **argv)
                }
        }
 
+       if (rec->timestamp_filename && record__threads_enabled(rec)) {
+               rec->timestamp_filename = false;
+               pr_warning("WARNING: --timestamp-filename option is not 
available in threaded streaming mode.\n");
+       }
+
        /*
         * Allow aliases to facilitate the lookup of symbols for address
         * filters. Refer to auxtrace_parse_filters().
-- 
2.24.1


Reply via email to