diff options
author | Namhyung Kim <namhyung@kernel.org> | 2017-01-13 05:45:22 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-01-17 09:36:44 -0500 |
commit | 414e050c68ec2a3dd815544ea48ff6016f1a7a11 (patch) | |
tree | e5b242a6167bc5dd384c7b5fdf715606d4cd58ad /tools/perf/builtin-sched.c | |
parent | 941bdea79e194dec7e7b42780aa5620020548f8a (diff) |
perf sched timehist: Add --state option
The --state option is to show task state when switched out. The state
is printed as a single character like in the /proc but I added 'I' for
idle state rather than 'R'.
$ perf sched timehist --state | head
Samples do not have callchains.
time cpu task name wait time sch delay run time state
[tid/pid] (msec) (msec) (msec)
-------- --- ----------------------- -------- ------------------ -----
1.753791 [3] <idle> 0.000 0.000 0.000 I
1.753834 [1] perf[27469] 0.000 0.000 0.000 S
1.753904 [3] perf[27470] 0.000 0.006 0.112 S
1.753914 [1] <idle> 0.000 0.000 0.079 I
1.753915 [3] migration/3[23] 0.000 0.002 0.011 S
1.754287 [2] <idle> 0.000 0.000 0.000 I
1.754335 [2] transmission[1773/1739] 0.000 0.004 0.047 S
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170113104523.31212-2-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r-- | tools/perf/builtin-sched.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 6d3c3e84881a..a8ac76602187 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -222,6 +222,7 @@ struct perf_sched { | |||
222 | bool show_cpu_visual; | 222 | bool show_cpu_visual; |
223 | bool show_wakeups; | 223 | bool show_wakeups; |
224 | bool show_migrations; | 224 | bool show_migrations; |
225 | bool show_state; | ||
225 | u64 skipped_samples; | 226 | u64 skipped_samples; |
226 | const char *time_str; | 227 | const char *time_str; |
227 | struct perf_time_interval ptime; | 228 | struct perf_time_interval ptime; |
@@ -1840,6 +1841,9 @@ static void timehist_header(struct perf_sched *sched) | |||
1840 | printf(" %-*s %9s %9s %9s", comm_width, | 1841 | printf(" %-*s %9s %9s %9s", comm_width, |
1841 | "task name", "wait time", "sch delay", "run time"); | 1842 | "task name", "wait time", "sch delay", "run time"); |
1842 | 1843 | ||
1844 | if (sched->show_state) | ||
1845 | printf(" %s", "state"); | ||
1846 | |||
1843 | printf("\n"); | 1847 | printf("\n"); |
1844 | 1848 | ||
1845 | /* | 1849 | /* |
@@ -1850,9 +1854,14 @@ static void timehist_header(struct perf_sched *sched) | |||
1850 | if (sched->show_cpu_visual) | 1854 | if (sched->show_cpu_visual) |
1851 | printf(" %*s ", ncpus, ""); | 1855 | printf(" %*s ", ncpus, ""); |
1852 | 1856 | ||
1853 | printf(" %-*s %9s %9s %9s\n", comm_width, | 1857 | printf(" %-*s %9s %9s %9s", comm_width, |
1854 | "[tid/pid]", "(msec)", "(msec)", "(msec)"); | 1858 | "[tid/pid]", "(msec)", "(msec)", "(msec)"); |
1855 | 1859 | ||
1860 | if (sched->show_state) | ||
1861 | printf(" %5s", ""); | ||
1862 | |||
1863 | printf("\n"); | ||
1864 | |||
1856 | /* | 1865 | /* |
1857 | * separator | 1866 | * separator |
1858 | */ | 1867 | */ |
@@ -1865,14 +1874,29 @@ static void timehist_header(struct perf_sched *sched) | |||
1865 | graph_dotted_line, graph_dotted_line, graph_dotted_line, | 1874 | graph_dotted_line, graph_dotted_line, graph_dotted_line, |
1866 | graph_dotted_line); | 1875 | graph_dotted_line); |
1867 | 1876 | ||
1877 | if (sched->show_state) | ||
1878 | printf(" %.5s", graph_dotted_line); | ||
1879 | |||
1868 | printf("\n"); | 1880 | printf("\n"); |
1869 | } | 1881 | } |
1870 | 1882 | ||
1883 | static char task_state_char(struct thread *thread, int state) | ||
1884 | { | ||
1885 | static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; | ||
1886 | unsigned bit = state ? ffs(state) : 0; | ||
1887 | |||
1888 | /* 'I' for idle */ | ||
1889 | if (thread->tid == 0) | ||
1890 | return 'I'; | ||
1891 | |||
1892 | return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?'; | ||
1893 | } | ||
1894 | |||
1871 | static void timehist_print_sample(struct perf_sched *sched, | 1895 | static void timehist_print_sample(struct perf_sched *sched, |
1872 | struct perf_sample *sample, | 1896 | struct perf_sample *sample, |
1873 | struct addr_location *al, | 1897 | struct addr_location *al, |
1874 | struct thread *thread, | 1898 | struct thread *thread, |
1875 | u64 t) | 1899 | u64 t, int state) |
1876 | { | 1900 | { |
1877 | struct thread_runtime *tr = thread__priv(thread); | 1901 | struct thread_runtime *tr = thread__priv(thread); |
1878 | u32 max_cpus = sched->max_cpu + 1; | 1902 | u32 max_cpus = sched->max_cpu + 1; |
@@ -1906,6 +1930,9 @@ static void timehist_print_sample(struct perf_sched *sched, | |||
1906 | print_sched_time(tr->dt_delay, 6); | 1930 | print_sched_time(tr->dt_delay, 6); |
1907 | print_sched_time(tr->dt_run, 6); | 1931 | print_sched_time(tr->dt_run, 6); |
1908 | 1932 | ||
1933 | if (sched->show_state) | ||
1934 | printf(" %5c ", task_state_char(thread, state)); | ||
1935 | |||
1909 | if (sched->show_wakeups) | 1936 | if (sched->show_wakeups) |
1910 | printf(" %-*s", comm_width, ""); | 1937 | printf(" %-*s", comm_width, ""); |
1911 | 1938 | ||
@@ -2406,6 +2433,8 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2406 | struct thread_runtime *tr = NULL; | 2433 | struct thread_runtime *tr = NULL; |
2407 | u64 tprev, t = sample->time; | 2434 | u64 tprev, t = sample->time; |
2408 | int rc = 0; | 2435 | int rc = 0; |
2436 | int state = perf_evsel__intval(evsel, sample, "prev_state"); | ||
2437 | |||
2409 | 2438 | ||
2410 | if (machine__resolve(machine, &al, sample) < 0) { | 2439 | if (machine__resolve(machine, &al, sample) < 0) { |
2411 | pr_err("problem processing %d event. skipping it\n", | 2440 | pr_err("problem processing %d event. skipping it\n", |
@@ -2493,7 +2522,7 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2493 | } | 2522 | } |
2494 | 2523 | ||
2495 | if (!sched->summary_only) | 2524 | if (!sched->summary_only) |
2496 | timehist_print_sample(sched, sample, &al, thread, t); | 2525 | timehist_print_sample(sched, sample, &al, thread, t, state); |
2497 | 2526 | ||
2498 | out: | 2527 | out: |
2499 | if (sched->hist_time.start == 0 && t >= ptime->start) | 2528 | if (sched->hist_time.start == 0 && t >= ptime->start) |
@@ -2506,7 +2535,7 @@ out: | |||
2506 | tr->last_time = sample->time; | 2535 | tr->last_time = sample->time; |
2507 | 2536 | ||
2508 | /* last state is used to determine where to account wait time */ | 2537 | /* last state is used to determine where to account wait time */ |
2509 | tr->last_state = perf_evsel__intval(evsel, sample, "prev_state"); | 2538 | tr->last_state = state; |
2510 | 2539 | ||
2511 | /* sched out event for task so reset ready to run time */ | 2540 | /* sched out event for task so reset ready to run time */ |
2512 | tr->ready_to_run = 0; | 2541 | tr->ready_to_run = 0; |
@@ -3278,6 +3307,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
3278 | OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"), | 3307 | OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"), |
3279 | OPT_STRING(0, "time", &sched.time_str, "str", | 3308 | OPT_STRING(0, "time", &sched.time_str, "str", |
3280 | "Time span for analysis (start,stop)"), | 3309 | "Time span for analysis (start,stop)"), |
3310 | OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"), | ||
3281 | OPT_PARENT(sched_options) | 3311 | OPT_PARENT(sched_options) |
3282 | }; | 3312 | }; |
3283 | 3313 | ||