perf sched: Add runtime stats
Extend the latency tracking structure with scheduling atom
runtime info - and sum it up during per task display.
(Also clean up a few details.)
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index a084c28..c382f53 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -243,8 +243,8 @@
nr_run_events++;
}
-static unsigned long targetless_wakeups;
-static unsigned long multitarget_wakeups;
+static unsigned long targetless_wakeups;
+static unsigned long multitarget_wakeups;
static void
add_sched_event_wakeup(struct task_desc *task, nsec_t timestamp,
@@ -485,10 +485,10 @@
}
}
-static nsec_t cpu_usage;
-static nsec_t runavg_cpu_usage;
-static nsec_t parent_cpu_usage;
-static nsec_t runavg_parent_cpu_usage;
+static nsec_t cpu_usage;
+static nsec_t runavg_cpu_usage;
+static nsec_t parent_cpu_usage;
+static nsec_t runavg_parent_cpu_usage;
static void wait_for_tasks(void)
{
@@ -858,9 +858,9 @@
}
static struct trace_sched_handler replay_ops = {
- .wakeup_event = replay_wakeup_event,
- .switch_event = replay_switch_event,
- .fork_event = replay_fork_event,
+ .wakeup_event = replay_wakeup_event,
+ .switch_event = replay_switch_event,
+ .fork_event = replay_fork_event,
};
#define TASK_STATE_TO_CHAR_STR "RSDTtZX"
@@ -877,6 +877,7 @@
enum thread_state state;
u64 wake_up_time;
u64 sched_in_time;
+ u64 runtime;
};
struct thread_latency {
@@ -951,6 +952,7 @@
/* should insert the newcomer */
}
+__used
static char sched_out_state(struct trace_switch_event *switch_event)
{
const char *str = TASK_STATE_TO_CHAR_STR;
@@ -960,17 +962,15 @@
static void
lat_sched_out(struct thread_latency *lat,
- struct trace_switch_event *switch_event)
+ struct trace_switch_event *switch_event __used, u64 delta)
{
struct lat_snapshot *snapshot;
- if (sched_out_state(switch_event) == 'R')
- return;
-
snapshot = calloc(sizeof(*snapshot), 1);
if (!snapshot)
die("Non memory");
+ snapshot->runtime = delta;
list_add_tail(&snapshot->list, &lat->snapshot_list);
}
@@ -997,16 +997,31 @@
snapshot->sched_in_time = timestamp;
}
-
static void
latency_switch_event(struct trace_switch_event *switch_event,
struct event *event __used,
- int cpu __used,
+ int cpu,
u64 timestamp,
struct thread *thread __used)
{
struct thread_latency *out_lat, *in_lat;
struct thread *sched_out, *sched_in;
+ u64 timestamp0;
+ s64 delta;
+
+ if (cpu >= MAX_CPUS || cpu < 0)
+ return;
+
+ timestamp0 = cpu_last_switched[cpu];
+ cpu_last_switched[cpu] = timestamp;
+ if (timestamp0)
+ delta = timestamp - timestamp0;
+ else
+ delta = 0;
+
+ if (delta < 0)
+ die("hm, delta: %Ld < 0 ?\n", delta);
+
sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match);
sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match);
@@ -1028,7 +1043,7 @@
}
lat_sched_in(in_lat, timestamp);
- lat_sched_out(out_lat, switch_event);
+ lat_sched_out(out_lat, switch_event, delta);
}
static void
@@ -1067,9 +1082,9 @@
}
static struct trace_sched_handler lat_ops = {
- .wakeup_event = latency_wakeup_event,
- .switch_event = latency_switch_event,
- .fork_event = latency_fork_event,
+ .wakeup_event = latency_wakeup_event,
+ .switch_event = latency_switch_event,
+ .fork_event = latency_fork_event,
};
static void output_lat_thread(struct thread_latency *lat)
@@ -1080,8 +1095,11 @@
int ret;
u64 max = 0, avg;
u64 total = 0, delta;
+ u64 total_runtime = 0;
list_for_each_entry(shot, &lat->snapshot_list, list) {
+ total_runtime += shot->runtime;
+
if (shot->state != THREAD_SCHED_IN)
continue;
@@ -1104,7 +1122,7 @@
avg = total / count;
printf("|%9.3f ms |%9d | avg:%9.3f ms | max:%9.3f ms |\n",
- 0.0, count, (double)avg/1e9, (double)max/1e9);
+ (double)total_runtime/1e9, count, (double)avg/1e9, (double)max/1e9);
}
static void __cmd_lat(void)