linux/tools/perf/util/kwork.h
Yang Jihong 8c98420987 perf kwork top: Implements BPF-based cpu usage statistics
Use BPF to collect statistics on the CPU usage based on perf BPF skeletons.

Example usage:

  # perf kwork top -h

   Usage: perf kwork top [<options>]

      -b, --use-bpf         Use BPF to measure task cpu usage
      -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): rate, runtime, tid
          --time <str>      Time span for analysis (start,stop)

  #
  # perf kwork -k sched top -b
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
  Total  : 160702.425 ms, 8 cpus
  %Cpu(s):  36.00% id,   0.00% hi,   0.00% si
  %Cpu0   [||||||||||||||||||              61.66%]
  %Cpu1   [||||||||||||||||||              61.27%]
  %Cpu2   [|||||||||||||||||||             66.40%]
  %Cpu3   [||||||||||||||||||              61.28%]
  %Cpu4   [||||||||||||||||||              61.82%]
  %Cpu5   [|||||||||||||||||||||||         77.41%]
  %Cpu6   [||||||||||||||||||              61.73%]
  %Cpu7   [||||||||||||||||||              63.25%]

        PID     SPID    %CPU           RUNTIME  COMMMAND
    -------------------------------------------------------------
          0        0   38.72       8089.463 ms  [swapper/1]
          0        0   38.71       8084.547 ms  [swapper/3]
          0        0   38.33       8007.532 ms  [swapper/0]
          0        0   38.26       7992.985 ms  [swapper/6]
          0        0   38.17       7971.865 ms  [swapper/4]
          0        0   36.74       7447.765 ms  [swapper/7]
          0        0   33.59       6486.942 ms  [swapper/2]
          0        0   22.58       3771.268 ms  [swapper/5]
       9545     9351    2.48        447.136 ms  sched-messaging
       9574     9351    2.09        418.583 ms  sched-messaging
       9724     9351    2.05        372.407 ms  sched-messaging
       9531     9351    2.01        368.804 ms  sched-messaging
       9512     9351    2.00        362.250 ms  sched-messaging
       9514     9351    1.95        357.767 ms  sched-messaging
       9538     9351    1.86        384.476 ms  sched-messaging
       9712     9351    1.84        386.490 ms  sched-messaging
       9723     9351    1.83        380.021 ms  sched-messaging
       9722     9351    1.82        382.738 ms  sched-messaging
       9517     9351    1.81        354.794 ms  sched-messaging
       9559     9351    1.79        344.305 ms  sched-messaging
       9725     9351    1.77        365.315 ms  sched-messaging
  <SNIP>

  # perf kwork -k sched top -b -n perf
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
  Total  : 151563.332 ms, 8 cpus
  %Cpu(s):  26.49% id,   0.00% hi,   0.00% si
  %Cpu0   [                                 0.01%]
  %Cpu1   [                                 0.00%]
  %Cpu2   [                                 0.00%]
  %Cpu3   [                                 0.00%]
  %Cpu4   [                                 0.00%]
  %Cpu5   [                                 0.00%]
  %Cpu6   [                                 0.00%]
  %Cpu7   [                                 0.00%]

        PID     SPID    %CPU           RUNTIME  COMMMAND
    -------------------------------------------------------------
       9754     9754    0.01          2.303 ms  perf

  #
  # perf kwork -k sched top -b -C 2,3,4
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
  Total  :  48016.721 ms, 3 cpus
  %Cpu(s):  27.82% id,   0.00% hi,   0.00% si
  %Cpu2   [||||||||||||||||||||||          74.68%]
  %Cpu3   [|||||||||||||||||||||           71.06%]
  %Cpu4   [|||||||||||||||||||||           70.91%]

        PID     SPID    %CPU           RUNTIME  COMMMAND
    -------------------------------------------------------------
          0        0   29.08       4734.998 ms  [swapper/4]
          0        0   28.93       4710.029 ms  [swapper/3]
          0        0   25.31       3912.363 ms  [swapper/2]
      10248    10158    1.62        264.931 ms  sched-messaging
      10253    10158    1.62        265.136 ms  sched-messaging
      10158    10158    1.60        263.013 ms  bash
      10360    10158    1.49        243.639 ms  sched-messaging
      10413    10158    1.48        238.604 ms  sched-messaging
      10531    10158    1.47        234.067 ms  sched-messaging
      10400    10158    1.47        240.631 ms  sched-messaging
      10355    10158    1.47        230.586 ms  sched-messaging
      10377    10158    1.43        234.835 ms  sched-messaging
      10526    10158    1.42        232.045 ms  sched-messaging
      10298    10158    1.41        222.396 ms  sched-messaging
      10410    10158    1.38        221.853 ms  sched-messaging
      10364    10158    1.38        226.042 ms  sched-messaging
      10480    10158    1.36        213.633 ms  sched-messaging
      10370    10158    1.36        223.620 ms  sched-messaging
      10553    10158    1.34        217.169 ms  sched-messaging
      10291    10158    1.34        211.516 ms  sched-messaging
      10251    10158    1.34        218.813 ms  sched-messaging
      10522    10158    1.33        218.498 ms  sched-messaging
      10288    10158    1.33        216.787 ms  sched-messaging
  <SNIP>

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Sandipan Das <sandipan.das@amd.com>
Link: https://lore.kernel.org/r/20230812084917.169338-15-yangjihong1@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2023-09-12 17:31:59 -03:00

315 lines
8.7 KiB
C

#ifndef PERF_UTIL_KWORK_H
#define PERF_UTIL_KWORK_H
#include "util/tool.h"
#include "util/time-utils.h"
#include <linux/bitmap.h>
#include <linux/list.h>
#include <linux/rbtree.h>
#include <linux/types.h>
struct perf_sample;
struct perf_session;
enum kwork_class_type {
KWORK_CLASS_IRQ,
KWORK_CLASS_SOFTIRQ,
KWORK_CLASS_WORKQUEUE,
KWORK_CLASS_SCHED,
KWORK_CLASS_MAX,
};
enum kwork_report_type {
KWORK_REPORT_RUNTIME,
KWORK_REPORT_LATENCY,
KWORK_REPORT_TIMEHIST,
KWORK_REPORT_TOP,
};
enum kwork_trace_type {
KWORK_TRACE_RAISE,
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 perf_kwork;
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;
/*
* latency report
*/
u64 max_latency;
u64 max_latency_start;
u64 max_latency_end;
u64 total_latency;
/*
* top report
*/
u32 cpu_usage;
u32 tgid;
bool is_kthread;
};
struct kwork_class {
struct list_head list;
const char *name;
enum kwork_class_type type;
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 perf_kwork *kwork,
struct kwork_class *class,
struct kwork_work *work,
enum kwork_trace_type src_type,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
void (*work_name)(struct kwork_work *work,
char *buf, int len);
};
struct trace_kwork_handler {
int (*raise_event)(struct perf_kwork *kwork,
struct kwork_class *class, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
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);
int (*sched_switch_event)(struct perf_kwork *kwork,
struct kwork_class *class, struct evsel *evsel,
struct perf_sample *sample, struct machine *machine);
};
struct __top_cpus_runtime {
u64 load;
u64 idle;
u64 irq;
u64 softirq;
u64 total;
};
struct kwork_top_stat {
DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS);
struct __top_cpus_runtime *cpus_runtime;
};
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;
bool show_callchain;
unsigned int max_stack;
bool use_bpf;
/*
* 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];
/*
* perf kwork top data
*/
struct kwork_top_stat top_stat;
};
struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork,
struct kwork_class *class,
struct kwork_work *key);
#ifdef HAVE_BPF_SKEL
int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork);
int perf_kwork__report_read_bpf(struct perf_kwork *kwork);
void perf_kwork__report_cleanup_bpf(void);
void perf_kwork__trace_start(void);
void perf_kwork__trace_finish(void);
int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork);
int perf_kwork__top_read_bpf(struct perf_kwork *kwork);
void perf_kwork__top_cleanup_bpf(void);
void perf_kwork__top_start(void);
void perf_kwork__top_finish(void);
#else /* !HAVE_BPF_SKEL */
static inline int
perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
{
return -1;
}
static inline int
perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused)
{
return -1;
}
static inline void perf_kwork__report_cleanup_bpf(void) {}
static inline void perf_kwork__trace_start(void) {}
static inline void perf_kwork__trace_finish(void) {}
static inline int
perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
{
return -1;
}
static inline int
perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused)
{
return -1;
}
static inline void perf_kwork__top_cleanup_bpf(void) {}
static inline void perf_kwork__top_start(void) {}
static inline void perf_kwork__top_finish(void) {}
#endif /* HAVE_BPF_SKEL */
#endif /* PERF_UTIL_KWORK_H */