diff options
author | Namhyung Kim <namhyung@kernel.org> | 2017-01-13 05:45:21 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-01-17 09:35:44 -0500 |
commit | 941bdea79e194dec7e7b42780aa5620020548f8a (patch) | |
tree | ceb6dfdad9cc51f7a98011d0676b4721907118c8 /tools/perf | |
parent | be3d466c7356e574a2aa4e19dd20b19b3a9cc4fc (diff) |
perf sched timehist: Account thread wait time separately
Separate thread wait time into 3 parts - sleep, iowait and preempt based
on the prev_state of the last event.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
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-1-namhyung@kernel.org
[ Fix the build on centos:5 where 'wait' shadows a global declaration ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-sched.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 5b134b0d1ff3..6d3c3e84881a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -77,6 +77,22 @@ struct sched_atom { | |||
77 | 77 | ||
78 | #define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" | 78 | #define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" |
79 | 79 | ||
80 | /* task state bitmask, copied from include/linux/sched.h */ | ||
81 | #define TASK_RUNNING 0 | ||
82 | #define TASK_INTERRUPTIBLE 1 | ||
83 | #define TASK_UNINTERRUPTIBLE 2 | ||
84 | #define __TASK_STOPPED 4 | ||
85 | #define __TASK_TRACED 8 | ||
86 | /* in tsk->exit_state */ | ||
87 | #define EXIT_DEAD 16 | ||
88 | #define EXIT_ZOMBIE 32 | ||
89 | #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) | ||
90 | /* in tsk->state again */ | ||
91 | #define TASK_DEAD 64 | ||
92 | #define TASK_WAKEKILL 128 | ||
93 | #define TASK_WAKING 256 | ||
94 | #define TASK_PARKED 512 | ||
95 | |||
80 | enum thread_state { | 96 | enum thread_state { |
81 | THREAD_SLEEPING = 0, | 97 | THREAD_SLEEPING = 0, |
82 | THREAD_WAIT_CPU, | 98 | THREAD_WAIT_CPU, |
@@ -216,13 +232,16 @@ struct perf_sched { | |||
216 | struct thread_runtime { | 232 | struct thread_runtime { |
217 | u64 last_time; /* time of previous sched in/out event */ | 233 | u64 last_time; /* time of previous sched in/out event */ |
218 | u64 dt_run; /* run time */ | 234 | u64 dt_run; /* run time */ |
219 | u64 dt_wait; /* time between CPU access (off cpu) */ | 235 | u64 dt_sleep; /* time between CPU access by sleep (off cpu) */ |
236 | u64 dt_iowait; /* time between CPU access by iowait (off cpu) */ | ||
237 | u64 dt_preempt; /* time between CPU access by preempt (off cpu) */ | ||
220 | u64 dt_delay; /* time between wakeup and sched-in */ | 238 | u64 dt_delay; /* time between wakeup and sched-in */ |
221 | u64 ready_to_run; /* time of wakeup */ | 239 | u64 ready_to_run; /* time of wakeup */ |
222 | 240 | ||
223 | struct stats run_stats; | 241 | struct stats run_stats; |
224 | u64 total_run_time; | 242 | u64 total_run_time; |
225 | 243 | ||
244 | int last_state; | ||
226 | u64 migrations; | 245 | u64 migrations; |
227 | }; | 246 | }; |
228 | 247 | ||
@@ -1858,6 +1877,7 @@ static void timehist_print_sample(struct perf_sched *sched, | |||
1858 | struct thread_runtime *tr = thread__priv(thread); | 1877 | struct thread_runtime *tr = thread__priv(thread); |
1859 | u32 max_cpus = sched->max_cpu + 1; | 1878 | u32 max_cpus = sched->max_cpu + 1; |
1860 | char tstr[64]; | 1879 | char tstr[64]; |
1880 | u64 wait_time; | ||
1861 | 1881 | ||
1862 | timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); | 1882 | timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); |
1863 | printf("%15s [%04d] ", tstr, sample->cpu); | 1883 | printf("%15s [%04d] ", tstr, sample->cpu); |
@@ -1880,7 +1900,9 @@ static void timehist_print_sample(struct perf_sched *sched, | |||
1880 | 1900 | ||
1881 | printf(" %-*s ", comm_width, timehist_get_commstr(thread)); | 1901 | printf(" %-*s ", comm_width, timehist_get_commstr(thread)); |
1882 | 1902 | ||
1883 | print_sched_time(tr->dt_wait, 6); | 1903 | wait_time = tr->dt_sleep + tr->dt_iowait + tr->dt_preempt; |
1904 | print_sched_time(wait_time, 6); | ||
1905 | |||
1884 | print_sched_time(tr->dt_delay, 6); | 1906 | print_sched_time(tr->dt_delay, 6); |
1885 | print_sched_time(tr->dt_run, 6); | 1907 | print_sched_time(tr->dt_run, 6); |
1886 | 1908 | ||
@@ -1930,8 +1952,11 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, | |||
1930 | u64 t, u64 tprev) | 1952 | u64 t, u64 tprev) |
1931 | { | 1953 | { |
1932 | r->dt_delay = 0; | 1954 | r->dt_delay = 0; |
1933 | r->dt_wait = 0; | 1955 | r->dt_sleep = 0; |
1956 | r->dt_iowait = 0; | ||
1957 | r->dt_preempt = 0; | ||
1934 | r->dt_run = 0; | 1958 | r->dt_run = 0; |
1959 | |||
1935 | if (tprev) { | 1960 | if (tprev) { |
1936 | r->dt_run = t - tprev; | 1961 | r->dt_run = t - tprev; |
1937 | if (r->ready_to_run) { | 1962 | if (r->ready_to_run) { |
@@ -1943,8 +1968,16 @@ static void timehist_update_runtime_stats(struct thread_runtime *r, | |||
1943 | 1968 | ||
1944 | if (r->last_time > tprev) | 1969 | if (r->last_time > tprev) |
1945 | pr_debug("time travel: last sched out time for task > previous sched_switch event\n"); | 1970 | pr_debug("time travel: last sched out time for task > previous sched_switch event\n"); |
1946 | else if (r->last_time) | 1971 | else if (r->last_time) { |
1947 | r->dt_wait = tprev - r->last_time; | 1972 | u64 dt_wait = tprev - r->last_time; |
1973 | |||
1974 | if (r->last_state == TASK_RUNNING) | ||
1975 | r->dt_preempt = dt_wait; | ||
1976 | else if (r->last_state == TASK_UNINTERRUPTIBLE) | ||
1977 | r->dt_iowait = dt_wait; | ||
1978 | else | ||
1979 | r->dt_sleep = dt_wait; | ||
1980 | } | ||
1948 | } | 1981 | } |
1949 | 1982 | ||
1950 | update_stats(&r->run_stats, r->dt_run); | 1983 | update_stats(&r->run_stats, r->dt_run); |
@@ -2447,8 +2480,10 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2447 | * time. we only care total run time and run stat. | 2480 | * time. we only care total run time and run stat. |
2448 | */ | 2481 | */ |
2449 | last_tr->dt_run = 0; | 2482 | last_tr->dt_run = 0; |
2450 | last_tr->dt_wait = 0; | ||
2451 | last_tr->dt_delay = 0; | 2483 | last_tr->dt_delay = 0; |
2484 | last_tr->dt_sleep = 0; | ||
2485 | last_tr->dt_iowait = 0; | ||
2486 | last_tr->dt_preempt = 0; | ||
2452 | 2487 | ||
2453 | if (itr->cursor.nr) | 2488 | if (itr->cursor.nr) |
2454 | callchain_append(&itr->callchain, &itr->cursor, t - tprev); | 2489 | callchain_append(&itr->callchain, &itr->cursor, t - tprev); |
@@ -2470,6 +2505,9 @@ out: | |||
2470 | /* time of this sched_switch event becomes last time task seen */ | 2505 | /* time of this sched_switch event becomes last time task seen */ |
2471 | tr->last_time = sample->time; | 2506 | tr->last_time = sample->time; |
2472 | 2507 | ||
2508 | /* last state is used to determine where to account wait time */ | ||
2509 | tr->last_state = perf_evsel__intval(evsel, sample, "prev_state"); | ||
2510 | |||
2473 | /* sched out event for task so reset ready to run time */ | 2511 | /* sched out event for task so reset ready to run time */ |
2474 | tr->ready_to_run = 0; | 2512 | tr->ready_to_run = 0; |
2475 | } | 2513 | } |