perf sched stats: Add support for live mode
The live mode works similar to simple `perf stat` command, by profiling the target and printing results on the terminal as soon as the target finishes. Example usage: # perf sched stats -- true Description ---------------------------------------------------------------------------------------------------- DESC -> Description of the field COUNT -> Value of the field PCT_CHANGE -> Percent change with corresponding base value AVG_JIFFIES -> Avg time in jiffies between two consecutive occurrence of event ---------------------------------------------------------------------------------------------------- Time elapsed (in jiffies) : 1 ---------------------------------------------------------------------------------------------------- CPU: <ALL CPUS SUMMARY> ---------------------------------------------------------------------------------------------------- DESC COUNT PCT_CHANGE ---------------------------------------------------------------------------------------------------- yld_count : 0 array_exp : 0 sched_count : 0 sched_goidle : 0 ( 0.00% ) ttwu_count : 0 ttwu_local : 0 ( 0.00% ) rq_cpu_time : 27875 run_delay : 0 ( 0.00% ) pcount : 0 ---------------------------------------------------------------------------------------------------- CPU: <ALL CPUS SUMMARY> | DOMAIN: SMT ---------------------------------------------------------------------------------------------------- DESC COUNT AVG_JIFFIES ----------------------------------------- <Category busy> ------------------------------------------ busy_lb_count : 0 $ 0.00 $ busy_lb_balanced : 0 $ 0.00 $ busy_lb_failed : 0 $ 0.00 $ busy_lb_imbalance_load : 0 busy_lb_imbalance_util : 0 busy_lb_imbalance_task : 0 busy_lb_imbalance_misfit : 0 busy_lb_gained : 0 busy_lb_hot_gained : 0 busy_lb_nobusyq : 0 $ 0.00 $ busy_lb_nobusyg : 0 $ 0.00 $ *busy_lb_success_count : 0 *busy_lb_avg_pulled : 0.00 ... and so on. Output will show similar data for all the cpus in the system. Co-developed-by: Ravi Bangoria <ravi.bangoria@amd.com> Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com> Signed-off-by: Swapnil Sapkal <swapnil.sapkal@amd.com> Tested-by: Chen Yu <yu.c.chen@intel.com> Tested-by: James Clark <james.clark@linaro.org> Acked-by: Ian Rogers <irogers@google.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Anubhav Shelat <ashelat@redhat.com> Cc: Ben Gainey <ben.gainey@arm.com> Cc: Blake Jones <blakejones@google.com> Cc: Chun-Tse Shao <ctshao@google.com> Cc: David Vernet <void@manifault.com> Cc: Dmitriy Vyukov <dvyukov@google.com> Cc: Dr. David Alan Gilbert <linux@treblig.org> Cc: Gautham Shenoy <gautham.shenoy@amd.com> Cc: Graham Woodward <graham.woodward@arm.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@arm.com> Cc: Madadi Vineeth Reddy <vineethr@linux.ibm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Santosh Shukla <santosh.shukla@amd.com> Cc: Shrikanth Hegde <sshegde@linux.ibm.com> Cc: Steven Rostedt (VMware) <rostedt@goodmis.org> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Vincent Guittot <vincent.guittot@linaro.org> Cc: Yang Jihong <yangjihong@bytedance.com> Cc: Yujie Liu <yujie.liu@intel.com> Cc: Zhongqiu Han <quic_zhonhan@quicinc.com> [ Avoid potentially using 'sv' uninitialized by calling free_cpu_domain_info() only when build_cpu_domain_map() is called ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
5a357ae6ad
commit
00093b3133
|
|
@ -4426,6 +4426,103 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int process_synthesized_event_live(const struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct machine *machine __maybe_unused)
|
||||
{
|
||||
return perf_sched__process_schedstat(tool, NULL, event);
|
||||
}
|
||||
|
||||
static int perf_sched__schedstat_live(struct perf_sched *sched,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
struct cpu_domain_map **cd_map = NULL;
|
||||
struct target target = {};
|
||||
u32 __maybe_unused md;
|
||||
struct evlist *evlist;
|
||||
u32 nr = 0, sv;
|
||||
int reset = 0;
|
||||
int err = 0;
|
||||
|
||||
signal(SIGINT, sighandler);
|
||||
signal(SIGCHLD, sighandler);
|
||||
signal(SIGTERM, sighandler);
|
||||
|
||||
evlist = evlist__new();
|
||||
if (!evlist)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* `perf sched schedstat` does not support workload profiling (-p pid)
|
||||
* since /proc/schedstat file contains cpu specific data only. Hence, a
|
||||
* profile target is either set of cpus or systemwide, never a process.
|
||||
* Note that, although `-- <workload>` is supported, profile data are
|
||||
* still cpu/systemwide.
|
||||
*/
|
||||
if (cpu_list)
|
||||
target.cpu_list = cpu_list;
|
||||
else
|
||||
target.system_wide = true;
|
||||
|
||||
if (argc) {
|
||||
err = evlist__prepare_workload(evlist, &target, argv, false, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = evlist__create_maps(evlist, &target);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
user_requested_cpus = evlist->core.user_requested_cpus;
|
||||
|
||||
err = perf_event__synthesize_schedstat(&(sched->tool),
|
||||
process_synthesized_event_live,
|
||||
user_requested_cpus);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = enable_sched_schedstats(&reset);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
if (argc)
|
||||
evlist__start_workload(evlist);
|
||||
|
||||
/* wait for signal */
|
||||
pause();
|
||||
|
||||
if (reset) {
|
||||
err = disable_sched_schedstat();
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = perf_event__synthesize_schedstat(&(sched->tool),
|
||||
process_synthesized_event_live,
|
||||
user_requested_cpus);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
setup_pager();
|
||||
|
||||
if (list_empty(&cpu_head)) {
|
||||
pr_err("Data is not available\n");
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nr = cpu__max_present_cpu().cpu;
|
||||
cd_map = build_cpu_domain_map(&sv, &md, nr);
|
||||
show_schedstat_data(&cpu_head, cd_map);
|
||||
free_cpu_domain_info(cd_map, sv, nr);
|
||||
out:
|
||||
free_schedstat(&cpu_head);
|
||||
evlist__delete(evlist);
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool schedstat_events_exposed(void)
|
||||
{
|
||||
/*
|
||||
|
|
@ -4751,7 +4848,7 @@ int cmd_sched(int argc, const char **argv)
|
|||
stats_usage, 0);
|
||||
return perf_sched__schedstat_report(&sched);
|
||||
}
|
||||
usage_with_options(stats_usage, stats_options);
|
||||
return perf_sched__schedstat_live(&sched, argc, argv);
|
||||
} else {
|
||||
usage_with_options(sched_usage, sched_options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1614,8 +1614,7 @@ static int write_pmu_caps(struct feat_fd *ff,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct cpu_domain_map **build_cpu_domain_map(u32 *schedstat_version, u32 *max_sched_domains,
|
||||
u32 nr)
|
||||
struct cpu_domain_map **build_cpu_domain_map(u32 *schedstat_version, u32 *max_sched_domains, u32 nr)
|
||||
{
|
||||
struct domain_info *domain_info;
|
||||
struct cpu_domain_map **cd_map;
|
||||
|
|
|
|||
|
|
@ -211,4 +211,7 @@ char *get_cpuid_str(struct perf_cpu cpu);
|
|||
char *get_cpuid_allow_env_override(struct perf_cpu cpu);
|
||||
|
||||
int strcmp_cpuid_str(const char *s1, const char *s2);
|
||||
|
||||
struct cpu_domain_map **build_cpu_domain_map(u32 *schedstat_version, u32 *max_sched_domains,
|
||||
u32 nr);
|
||||
#endif /* __PERF_HEADER_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue