Commit f98919ec authored by Yang Jihong's avatar Yang Jihong Committed by Arnaldo Carvalho de Melo

perf kwork: Implement 'report' subcommand

Implements framework of 'perf kwork report', which is used to report
time properties such as run time and frequency:

Test cases:

  # perf kwork

   Usage: perf kwork [<options>] {record|report}

      -D, --dump-raw-trace  dump raw trace in ASCII
      -f, --force           don't complain, do it
      -k, --kwork <kwork>   list of kwork to profile (irq, softirq, workqueue, etc)
      -v, --verbose         be more verbose (show symbol address, etc)

  # perf kwork report -h

   Usage: perf kwork report [<options>]

      -C, --cpu <cpu>       list of cpus to profile
      -i, --input <file>    input file name
      -n, --name <name>     event name to profile
      -s, --sort <key[,key2...]>
                            sort by key(s): runtime, max, count
      -S, --with-summary    Show summary with statistics
          --time <str>      Time span for analysis (start,stop)

  # perf kwork report

    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------------------

  # perf kwork report -S

    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------------------
    Total count            :         0
    Total runtime   (msec) :     0.000 (0.000% load average)
    Total time span (msec) :     0.000
   --------------------------------------------------------------------------------------------------------------------------------

  # perf kwork report -C 0,100
  Requested CPU 100 too large. Consider raising MAX_NR_CPUS
  Invalid cpu bitmap

  # perf kwork report -s runtime1
    Error: Unknown --sort key: `runtime1'

   Usage: perf kwork report [<options>]

      -C, --cpu <cpu>       list of cpus to profile
      -i, --input <file>    input file name
      -n, --name <name>     event name to profile
      -s, --sort <key[,key2...]>
                            sort by key(s): runtime, max, count
      -S, --with-summary    Show summary with statistics
          --time <str>      Time span for analysis (start,stop)

  # perf kwork report -i perf_no_exist.data
  failed to open perf_no_exist.data: No such file or directory

  # perf kwork report --time 00FFF,
  Invalid time span

Since there are no report supported events, the output is empty.

Briefly describe the data structure:

1. "class" indicates event type. For example, irq and softiq correspond
to different types.

2. "cluster" refers to a specific event corresponding to a type. For
example, RCU and TIMER in softirq correspond to different clusters,
which contains three types of events: raise, entry, and exit.

3. "atom" includes time of each sample and sample of the previous phase.
(For example, exit corresponds to entry, which is used for timehist.)

Committer notes:

- Add {} for multiline if blocks.

- report_print_work() should either return that ret variable that
  accounts how many bytes were printed or stop accounting and be void.
  Do the former for now to avoid this:

builtin-kwork.c:534:6: error: variable 'ret' set but not used [-Werror,-Wunused-but-set-variable]
        int ret = 0;
            ^
1 error generated.

  When building with:

  ⬢[acme@toolbox perf]$ clang --version
  clang version 13.0.0 (https://github.com/llvm/llvm-project e8991caea8690ec2d17b0b7e1c29bf0da6609076)

Also:

  -       if ((dst_type >= 0) && (dst_type < KWORK_TRACE_MAX)) {
  +       if (dst_type < KWORK_TRACE_MAX) {

Several versions of clang and at least this gcc:

   3    51.40 alpine:3.9                    : FAIL gcc version 8.3.0 (Alpine 8.3.0)
    builtin-kwork.c:411:16: error: comparison of unsigned enum expression >= 0 is
          always true [-Werror,-Wtautological-compare]
            if ((dst_type >= 0) && (dst_type < KWORK_TRACE_MAX)) {

As the first entry in a enum is zero.
Signed-off-by: default avatarYang Jihong <yangjihong1@huawei.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220709015033.38326-7-yangjihong1@huawei.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e432947e
......@@ -17,8 +17,11 @@ There are several variants of 'perf kwork':
'perf kwork record <command>' to record the kernel work
of an arbitrary workload.
'perf kwork report' to report the per kwork runtime.
Example usage:
perf kwork record -- sleep 1
perf kwork report
OPTIONS
-------
......@@ -38,6 +41,36 @@ OPTIONS
--verbose::
Be more verbose. (show symbol address, etc)
OPTIONS for 'perf kwork report'
----------------------------
-C::
--cpu::
Only show events for the given CPU(s) (comma separated list).
-i::
--input::
Input file name. (default: perf.data unless stdin is a fifo)
-n::
--name::
Only show events for the given name.
-s::
--sort::
Sort by key(s): runtime, max, count
-S::
--with-summary::
Show summary with statistics
--time::
Only analyze samples within given time window: <start>,<stop>. Times
have the format seconds.microseconds. If start is not given (i.e., time
string is ',x.y') then analysis starts at the beginning of the file. If
stop time is not given (i.e, time string is 'x.y,') then analysis goes
to end of file.
SEE ALSO
--------
linkperf:perf-record[1]
This diff is collapsed.
......@@ -19,6 +19,105 @@ enum kwork_class_type {
KWORK_CLASS_MAX,
};
enum kwork_report_type {
KWORK_REPORT_RUNTIME,
};
enum kwork_trace_type {
KWORK_TRACE_ENTRY,
KWORK_TRACE_EXIT,
KWORK_TRACE_MAX,
};
/*
* data structure:
*
* +==================+ +============+ +======================+
* | class | | work | | atom |
* +==================+ +============+ +======================+
* +------------+ | +-----+ | | +------+ | | +-------+ +-----+ |
* | perf_kwork | +-> | irq | --------|+-> | eth0 | --+-> | raise | - | ... | --+ +-----------+
* +-----+------+ || +-----+ ||| +------+ ||| +-------+ +-----+ | | | |
* | || ||| ||| | +-> | atom_page |
* | || ||| ||| +-------+ +-----+ | | |
* | class_list ||| |+-> | entry | - | ... | ----> | |
* | || ||| ||| +-------+ +-----+ | | |
* | || ||| ||| | +-> | |
* | || ||| ||| +-------+ +-----+ | | | |
* | || ||| |+-> | exit | - | ... | --+ +-----+-----+
* | || ||| | | +-------+ +-----+ | |
* | || ||| | | | |
* | || ||| +-----+ | | | |
* | || |+-> | ... | | | | |
* | || | | +-----+ | | | |
* | || | | | | | |
* | || +---------+ | | +-----+ | | +-------+ +-----+ | |
* | +-> | softirq | -------> | RCU | ---+-> | raise | - | ... | --+ +-----+-----+
* | || +---------+ | | +-----+ ||| +-------+ +-----+ | | | |
* | || | | ||| | +-> | atom_page |
* | || | | ||| +-------+ +-----+ | | |
* | || | | |+-> | entry | - | ... | ----> | |
* | || | | ||| +-------+ +-----+ | | |
* | || | | ||| | +-> | |
* | || | | ||| +-------+ +-----+ | | | |
* | || | | |+-> | exit | - | ... | --+ +-----+-----+
* | || | | | | +-------+ +-----+ | |
* | || | | | | | |
* | || +-----------+ | | +-----+ | | | |
* | +-> | workqueue | -----> | ... | | | | |
* | | +-----------+ | | +-----+ | | | |
* | +==================+ +============+ +======================+ |
* | |
* +----> atom_page_list ---------------------------------------------------------+
*
*/
struct kwork_atom {
struct list_head list;
u64 time;
struct kwork_atom *prev;
void *page_addr;
unsigned long bit_inpage;
};
#define NR_ATOM_PER_PAGE 128
struct kwork_atom_page {
struct list_head list;
struct kwork_atom atoms[NR_ATOM_PER_PAGE];
DECLARE_BITMAP(bitmap, NR_ATOM_PER_PAGE);
};
struct kwork_class;
struct kwork_work {
/*
* class field
*/
struct rb_node node;
struct kwork_class *class;
/*
* work field
*/
u64 id;
int cpu;
char *name;
/*
* atom field
*/
u64 nr_atoms;
struct list_head atom_list[KWORK_TRACE_MAX];
/*
* runtime report
*/
u64 max_runtime;
u64 max_runtime_start;
u64 max_runtime_end;
u64 total_runtime;
};
struct kwork_class {
struct list_head list;
const char *name;
......@@ -26,19 +125,81 @@ struct kwork_class {
unsigned int nr_tracepoints;
const struct evsel_str_handler *tp_handlers;
struct rb_root_cached work_root;
int (*class_init)(struct kwork_class *class,
struct perf_session *session);
void (*work_init)(struct kwork_class *class,
struct kwork_work *work,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
void (*work_name)(struct kwork_work *work,
char *buf, int len);
};
struct perf_kwork;
struct trace_kwork_handler {
int (*entry_event)(struct perf_kwork *kwork,
struct kwork_class *class, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
int (*exit_event)(struct perf_kwork *kwork,
struct kwork_class *class, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
};
struct perf_kwork {
/*
* metadata
*/
struct perf_tool tool;
struct list_head class_list;
struct list_head atom_page_list;
struct list_head sort_list, cmp_id;
struct rb_root_cached sorted_work_root;
const struct trace_kwork_handler *tp_handler;
/*
* profile filters
*/
const char *profile_name;
const char *cpu_list;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
const char *time_str;
struct perf_time_interval ptime;
/*
* options for command
*/
bool force;
const char *event_list_str;
enum kwork_report_type report;
/*
* options for subcommand
*/
bool summary;
const char *sort_order;
/*
* statistics
*/
u64 timestart;
u64 timeend;
unsigned long nr_events;
unsigned long nr_lost_chunks;
unsigned long nr_lost_events;
u64 all_runtime;
u64 all_count;
u64 nr_skipped_events[KWORK_TRACE_MAX + 1];
};
#endif /* PERF_UTIL_KWORK_H */
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