2009-09-11 18:12:54 +08:00
|
|
|
#include "builtin.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
#include "perf.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
#include "util/util.h"
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
#include "util/evlist.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
#include "util/cache.h"
|
2011-11-17 03:02:54 +08:00
|
|
|
#include "util/evsel.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
#include "util/symbol.h"
|
|
|
|
#include "util/thread.h"
|
|
|
|
#include "util/header.h"
|
2009-12-12 07:24:02 +08:00
|
|
|
#include "util/session.h"
|
2011-11-28 18:30:20 +08:00
|
|
|
#include "util/tool.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
#include "util/parse-options.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
#include "util/trace-event.h"
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
#include "util/debug.h"
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
#include <sys/prctl.h>
|
2012-04-04 16:45:27 +08:00
|
|
|
#include <sys/resource.h>
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
#include <semaphore.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <math.h>
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2011-12-07 17:02:54 +08:00
|
|
|
static const char *input_name;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-13 09:36:29 +08:00
|
|
|
static char default_sort_order[] = "avg, max, switch, runtime";
|
2010-05-18 03:22:41 +08:00
|
|
|
static const char *sort_order = default_sort_order;
|
2009-09-13 09:36:29 +08:00
|
|
|
|
2009-10-10 20:46:04 +08:00
|
|
|
static int profile_cpu = -1;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
#define PR_SET_NAME 15 /* Set process name */
|
|
|
|
#define MAX_CPUS 4096
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static u64 run_measurement_overhead;
|
|
|
|
static u64 sleep_measurement_overhead;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
#define COMM_LEN 20
|
|
|
|
#define SYM_LEN 129
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
#define MAX_PID 65536
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static unsigned long nr_tasks;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
struct task_desc {
|
|
|
|
unsigned long nr;
|
|
|
|
unsigned long pid;
|
|
|
|
char comm[COMM_LEN];
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
unsigned long nr_events;
|
|
|
|
unsigned long curr_event;
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom **atoms;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
pthread_t thread;
|
|
|
|
sem_t sleep_sem;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
sem_t ready_for_work;
|
|
|
|
sem_t work_done_sem;
|
|
|
|
|
|
|
|
u64 cpu_usage;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum sched_event_type {
|
|
|
|
SCHED_EVENT_RUN,
|
|
|
|
SCHED_EVENT_SLEEP,
|
|
|
|
SCHED_EVENT_WAKEUP,
|
2009-10-10 20:46:04 +08:00
|
|
|
SCHED_EVENT_MIGRATION,
|
2009-09-11 18:12:54 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom {
|
2009-09-11 18:12:54 +08:00
|
|
|
enum sched_event_type type;
|
perf tools: Reorganize some structs to save space
Using 'pahole --packable' I found some structs that could be reorganized
to eliminate alignment holes, in some cases getting them to be cacheline
multiples.
[acme@doppio linux-2.6-tip]$ codiff perf.old ~/bin/perf
builtin-annotate.c:
struct perf_session | -8
struct perf_header | -8
2 structs changed
builtin-diff.c:
struct sample_data | -8
1 struct changed
diff__process_sample_event | -8
1 function changed, 8 bytes removed, diff: -8
builtin-sched.c:
struct sched_atom | -8
1 struct changed
builtin-timechart.c:
struct per_pid | -8
1 struct changed
cmd_timechart | -16
1 function changed, 16 bytes removed, diff: -16
builtin-probe.c:
struct perf_probe_point | -8
struct perf_probe_event | -8
2 structs changed
opt_add_probe_event | -3
1 function changed, 3 bytes removed, diff: -3
util/probe-finder.c:
struct probe_finder | -8
1 struct changed
find_kprobe_trace_events | -16
1 function changed, 16 bytes removed, diff: -16
/home/acme/bin/perf:
4 functions changed, 43 bytes removed, diff: -43
[acme@doppio linux-2.6-tip]$
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2010-04-05 23:53:45 +08:00
|
|
|
int specific_wait;
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 timestamp;
|
|
|
|
u64 duration;
|
|
|
|
unsigned long nr;
|
|
|
|
sem_t *wait_sem;
|
|
|
|
struct task_desc *wakee;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct task_desc *pid_to_task[MAX_PID];
|
|
|
|
|
|
|
|
static struct task_desc **tasks;
|
|
|
|
|
|
|
|
static pthread_mutex_t start_work_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
static u64 start_time;
|
|
|
|
|
|
|
|
static pthread_mutex_t work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static unsigned long nr_run_events;
|
|
|
|
static unsigned long nr_sleep_events;
|
|
|
|
static unsigned long nr_wakeup_events;
|
|
|
|
|
|
|
|
static unsigned long nr_sleep_corrections;
|
|
|
|
static unsigned long nr_run_events_optimized;
|
|
|
|
|
|
|
|
static unsigned long targetless_wakeups;
|
|
|
|
static unsigned long multitarget_wakeups;
|
|
|
|
|
|
|
|
static u64 cpu_usage;
|
|
|
|
static u64 runavg_cpu_usage;
|
|
|
|
static u64 parent_cpu_usage;
|
|
|
|
static u64 runavg_parent_cpu_usage;
|
|
|
|
|
|
|
|
static unsigned long nr_runs;
|
|
|
|
static u64 sum_runtime;
|
|
|
|
static u64 sum_fluct;
|
|
|
|
static u64 run_avg;
|
|
|
|
|
2010-05-18 02:39:16 +08:00
|
|
|
static unsigned int replay_repeat = 10;
|
2009-09-14 00:15:54 +08:00
|
|
|
static unsigned long nr_timestamps;
|
2009-09-16 19:45:00 +08:00
|
|
|
static unsigned long nr_unordered_timestamps;
|
|
|
|
static unsigned long nr_state_machine_bugs;
|
2009-09-16 20:07:00 +08:00
|
|
|
static unsigned long nr_context_switch_bugs;
|
2009-09-16 19:45:00 +08:00
|
|
|
static unsigned long nr_events;
|
|
|
|
static unsigned long nr_lost_chunks;
|
|
|
|
static unsigned long nr_lost_events;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
#define TASK_STATE_TO_CHAR_STR "RSDTtZX"
|
|
|
|
|
|
|
|
enum thread_state {
|
|
|
|
THREAD_SLEEPING = 0,
|
|
|
|
THREAD_WAIT_CPU,
|
|
|
|
THREAD_SCHED_IN,
|
|
|
|
THREAD_IGNORE
|
|
|
|
};
|
|
|
|
|
|
|
|
struct work_atom {
|
|
|
|
struct list_head list;
|
|
|
|
enum thread_state state;
|
perf tools: Fix processing of randomly serialized sched traces
Currently it's possible to meet such too high latency results
with 'perf sched latency'.
-----------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------
xfce4-panel | 0.222 ms | 2 | avg: 4718.345 ms | max: 9436.493 ms |
scsi_eh_3 | 3.962 ms | 36 | avg: 55.957 ms | max: 1977.829 ms |
The origin is on traces that are sometimes badly serialized across cpus.
For example the raw traces that raised such results for xfce4-panel:
(1) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(2) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(3) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
The traces are processed in the order they arrive. Then in (2),
xfce4-panel sleeps, it is first waken up in (3) and eventually
scheduled in (5).
The latency reported is then 1504 - 1495 = 9 secs, as reported by perf
sched. But this is wrong, we are confident in the fact the traces are
nicely serialized while we should actually more trust the timestamps.
If we reorder by timestamps we get:
(1) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(2) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(3) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
Now the trace make more sense, xfce4-panel is sleeping. Then it is
woken up in (1), scheduled in (2)
It goes to sleep in (3), woken up in (4) and scheduled in (5).
Now, latency captured between (1) and (2) is of 39 us.
And between (4) and (5) it is 2.1 ms.
Such pattern of bad serializing is the origin of the high latencies
reported by perf sched.
Basically, we need to check whether wake up time is higher than
schedule out time. If it's not the case, we need to tag the current
work atom as invalid.
Beside that, we may need to work later on a better ordering of the
traces given by the kernel.
After this patch:
xfce4-session | 0.221 ms | 1 | avg: 0.538 ms | max: 0.538 ms |
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-14 09:01:12 +08:00
|
|
|
u64 sched_out_time;
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 wake_up_time;
|
|
|
|
u64 sched_in_time;
|
|
|
|
u64 runtime;
|
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms {
|
|
|
|
struct list_head work_list;
|
2009-09-11 18:12:54 +08:00
|
|
|
struct thread *thread;
|
|
|
|
struct rb_node node;
|
|
|
|
u64 max_lat;
|
2009-12-10 04:40:08 +08:00
|
|
|
u64 max_lat_at;
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 total_lat;
|
|
|
|
u64 nb_atoms;
|
|
|
|
u64 total_runtime;
|
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
static struct rb_root atom_root, sorted_atom_root;
|
|
|
|
|
|
|
|
static u64 all_runtime;
|
|
|
|
static u64 all_count;
|
|
|
|
|
|
|
|
|
|
|
|
static u64 get_nsecs(void)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
|
|
|
|
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static void burn_nsecs(u64 nsecs)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 T0 = get_nsecs(), T1;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
T1 = get_nsecs();
|
|
|
|
} while (T1 + run_measurement_overhead < T0 + nsecs);
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static void sleep_nsecs(u64 nsecs)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
|
|
|
|
ts.tv_nsec = nsecs % 999999999;
|
|
|
|
ts.tv_sec = nsecs / 999999999;
|
|
|
|
|
|
|
|
nanosleep(&ts, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void calibrate_run_measurement_overhead(void)
|
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 T0, T1, delta, min_delta = 1000000000ULL;
|
2009-09-11 18:12:54 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
T0 = get_nsecs();
|
|
|
|
burn_nsecs(0);
|
|
|
|
T1 = get_nsecs();
|
|
|
|
delta = T1-T0;
|
|
|
|
min_delta = min(min_delta, delta);
|
|
|
|
}
|
|
|
|
run_measurement_overhead = min_delta;
|
|
|
|
|
2011-01-23 06:37:02 +08:00
|
|
|
printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta);
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void calibrate_sleep_measurement_overhead(void)
|
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 T0, T1, delta, min_delta = 1000000000ULL;
|
2009-09-11 18:12:54 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
T0 = get_nsecs();
|
|
|
|
sleep_nsecs(10000);
|
|
|
|
T1 = get_nsecs();
|
|
|
|
delta = T1-T0;
|
|
|
|
min_delta = min(min_delta, delta);
|
|
|
|
}
|
|
|
|
min_delta -= 10000;
|
|
|
|
sleep_measurement_overhead = min_delta;
|
|
|
|
|
2011-01-23 06:37:02 +08:00
|
|
|
printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta);
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static struct sched_atom *
|
2009-09-11 18:12:54 +08:00
|
|
|
get_new_event(struct task_desc *task, u64 timestamp)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-11-24 22:05:16 +08:00
|
|
|
struct sched_atom *event = zalloc(sizeof(*event));
|
2009-09-11 18:12:54 +08:00
|
|
|
unsigned long idx = task->nr_events;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
event->timestamp = timestamp;
|
|
|
|
event->nr = idx;
|
|
|
|
|
|
|
|
task->nr_events++;
|
2009-09-15 02:04:48 +08:00
|
|
|
size = sizeof(struct sched_atom *) * task->nr_events;
|
|
|
|
task->atoms = realloc(task->atoms, size);
|
|
|
|
BUG_ON(!task->atoms);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
task->atoms[idx] = event;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static struct sched_atom *last_event(struct task_desc *task)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
|
|
|
if (!task->nr_events)
|
|
|
|
return NULL;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
return task->atoms[task->nr_events - 1];
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-11 18:12:54 +08:00
|
|
|
add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom *event, *curr_event = last_event(task);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
/*
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
* optimize an existing RUN event by merging this one
|
|
|
|
* to it:
|
|
|
|
*/
|
2009-09-11 18:12:54 +08:00
|
|
|
if (curr_event && curr_event->type == SCHED_EVENT_RUN) {
|
|
|
|
nr_run_events_optimized++;
|
|
|
|
curr_event->duration += duration;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = get_new_event(task, timestamp);
|
|
|
|
|
|
|
|
event->type = SCHED_EVENT_RUN;
|
|
|
|
event->duration = duration;
|
|
|
|
|
|
|
|
nr_run_events++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-11 18:12:54 +08:00
|
|
|
add_sched_event_wakeup(struct task_desc *task, u64 timestamp,
|
2009-09-11 18:12:54 +08:00
|
|
|
struct task_desc *wakee)
|
|
|
|
{
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom *event, *wakee_event;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
event = get_new_event(task, timestamp);
|
|
|
|
event->type = SCHED_EVENT_WAKEUP;
|
|
|
|
event->wakee = wakee;
|
|
|
|
|
|
|
|
wakee_event = last_event(wakee);
|
|
|
|
if (!wakee_event || wakee_event->type != SCHED_EVENT_SLEEP) {
|
|
|
|
targetless_wakeups++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (wakee_event->wait_sem) {
|
|
|
|
multitarget_wakeups++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-11-24 22:05:16 +08:00
|
|
|
wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem));
|
2009-09-11 18:12:54 +08:00
|
|
|
sem_init(wakee_event->wait_sem, 0, 0);
|
|
|
|
wakee_event->specific_wait = 1;
|
|
|
|
event->wait_sem = wakee_event->wait_sem;
|
|
|
|
|
|
|
|
nr_wakeup_events++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-11 18:12:54 +08:00
|
|
|
add_sched_event_sleep(struct task_desc *task, u64 timestamp,
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 task_state __used)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-09-15 02:04:48 +08:00
|
|
|
struct sched_atom *event = get_new_event(task, timestamp);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
event->type = SCHED_EVENT_SLEEP;
|
|
|
|
|
|
|
|
nr_sleep_events++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct task_desc *register_pid(unsigned long pid, const char *comm)
|
|
|
|
{
|
|
|
|
struct task_desc *task;
|
|
|
|
|
|
|
|
BUG_ON(pid >= MAX_PID);
|
|
|
|
|
|
|
|
task = pid_to_task[pid];
|
|
|
|
|
|
|
|
if (task)
|
|
|
|
return task;
|
|
|
|
|
2009-11-24 22:05:16 +08:00
|
|
|
task = zalloc(sizeof(*task));
|
2009-09-11 18:12:54 +08:00
|
|
|
task->pid = pid;
|
|
|
|
task->nr = nr_tasks;
|
|
|
|
strcpy(task->comm, comm);
|
|
|
|
/*
|
|
|
|
* every task starts in sleeping state - this gets ignored
|
|
|
|
* if there's no wakeup pointing to this sleep state:
|
|
|
|
*/
|
|
|
|
add_sched_event_sleep(task, 0, 0);
|
|
|
|
|
|
|
|
pid_to_task[pid] = task;
|
|
|
|
nr_tasks++;
|
|
|
|
tasks = realloc(tasks, nr_tasks*sizeof(struct task_task *));
|
|
|
|
BUG_ON(!tasks);
|
|
|
|
tasks[task->nr] = task;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (verbose)
|
|
|
|
printf("registered task #%ld, PID %ld (%s)\n", nr_tasks, pid, comm);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
return task;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void print_task_traces(void)
|
|
|
|
{
|
|
|
|
struct task_desc *task;
|
|
|
|
unsigned long i;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task = tasks[i];
|
2009-09-11 18:12:54 +08:00
|
|
|
printf("task %6ld (%20s:%10ld), nr_events: %ld\n",
|
2009-09-11 18:12:54 +08:00
|
|
|
task->nr, task->comm, task->pid, task->nr_events);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_cross_task_wakeups(void)
|
|
|
|
{
|
|
|
|
struct task_desc *task1, *task2;
|
|
|
|
unsigned long i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task1 = tasks[i];
|
|
|
|
j = i + 1;
|
|
|
|
if (j == nr_tasks)
|
|
|
|
j = 0;
|
|
|
|
task2 = tasks[j];
|
|
|
|
add_sched_event_wakeup(task1, 0, task2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-15 02:04:48 +08:00
|
|
|
process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
switch (atom->type) {
|
2009-09-11 18:12:54 +08:00
|
|
|
case SCHED_EVENT_RUN:
|
2009-09-15 02:04:48 +08:00
|
|
|
burn_nsecs(atom->duration);
|
2009-09-11 18:12:54 +08:00
|
|
|
break;
|
|
|
|
case SCHED_EVENT_SLEEP:
|
2009-09-15 02:04:48 +08:00
|
|
|
if (atom->wait_sem)
|
|
|
|
ret = sem_wait(atom->wait_sem);
|
2009-09-11 18:12:54 +08:00
|
|
|
BUG_ON(ret);
|
|
|
|
break;
|
|
|
|
case SCHED_EVENT_WAKEUP:
|
2009-09-15 02:04:48 +08:00
|
|
|
if (atom->wait_sem)
|
|
|
|
ret = sem_post(atom->wait_sem);
|
2009-09-11 18:12:54 +08:00
|
|
|
BUG_ON(ret);
|
|
|
|
break;
|
2009-10-10 20:46:04 +08:00
|
|
|
case SCHED_EVENT_MIGRATION:
|
|
|
|
break;
|
2009-09-11 18:12:54 +08:00
|
|
|
default:
|
|
|
|
BUG_ON(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static u64 get_cpu_usage_nsec_parent(void)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
|
|
|
struct rusage ru;
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 sum;
|
2009-09-11 18:12:54 +08:00
|
|
|
int err;
|
|
|
|
|
|
|
|
err = getrusage(RUSAGE_SELF, &ru);
|
|
|
|
BUG_ON(err);
|
|
|
|
|
|
|
|
sum = ru.ru_utime.tv_sec*1e9 + ru.ru_utime.tv_usec*1e3;
|
|
|
|
sum += ru.ru_stime.tv_sec*1e9 + ru.ru_stime.tv_usec*1e3;
|
|
|
|
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
static int self_open_counters(void)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-12-09 17:51:30 +08:00
|
|
|
struct perf_event_attr attr;
|
|
|
|
int fd;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
memset(&attr, 0, sizeof(attr));
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
attr.type = PERF_TYPE_SOFTWARE;
|
|
|
|
attr.config = PERF_COUNT_SW_TASK_CLOCK;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
|
|
|
|
|
|
|
|
if (fd < 0)
|
2012-09-09 09:53:06 +08:00
|
|
|
pr_debug("Error: sys_perf_event_open() syscall returned"
|
|
|
|
"with %d (%s)\n", fd, strerror(errno));
|
2009-12-09 17:51:30 +08:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u64 get_cpu_usage_nsec_self(int fd)
|
|
|
|
{
|
|
|
|
u64 runtime;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = read(fd, &runtime, sizeof(runtime));
|
|
|
|
BUG_ON(ret != sizeof(runtime));
|
|
|
|
|
|
|
|
return runtime;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *thread_func(void *ctx)
|
|
|
|
{
|
|
|
|
struct task_desc *this_task = ctx;
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 cpu_usage_0, cpu_usage_1;
|
2009-09-11 18:12:54 +08:00
|
|
|
unsigned long i, ret;
|
|
|
|
char comm2[22];
|
2009-12-09 17:51:30 +08:00
|
|
|
int fd;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
sprintf(comm2, ":%s", this_task->comm);
|
|
|
|
prctl(PR_SET_NAME, comm2);
|
2009-12-09 17:51:30 +08:00
|
|
|
fd = self_open_counters();
|
2012-09-09 09:53:06 +08:00
|
|
|
if (fd < 0)
|
|
|
|
return NULL;
|
2009-09-11 18:12:54 +08:00
|
|
|
again:
|
|
|
|
ret = sem_post(&this_task->ready_for_work);
|
|
|
|
BUG_ON(ret);
|
|
|
|
ret = pthread_mutex_lock(&start_work_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
ret = pthread_mutex_unlock(&start_work_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
cpu_usage_0 = get_cpu_usage_nsec_self(fd);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
for (i = 0; i < this_task->nr_events; i++) {
|
|
|
|
this_task->curr_event = i;
|
2009-09-15 02:04:48 +08:00
|
|
|
process_sched_event(this_task, this_task->atoms[i]);
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2009-12-09 17:51:30 +08:00
|
|
|
cpu_usage_1 = get_cpu_usage_nsec_self(fd);
|
2009-09-11 18:12:54 +08:00
|
|
|
this_task->cpu_usage = cpu_usage_1 - cpu_usage_0;
|
|
|
|
ret = sem_post(&this_task->work_done_sem);
|
|
|
|
BUG_ON(ret);
|
|
|
|
|
|
|
|
ret = pthread_mutex_lock(&work_done_wait_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
ret = pthread_mutex_unlock(&work_done_wait_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void create_tasks(void)
|
|
|
|
{
|
|
|
|
struct task_desc *task;
|
|
|
|
pthread_attr_t attr;
|
|
|
|
unsigned long i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = pthread_attr_init(&attr);
|
|
|
|
BUG_ON(err);
|
2011-01-11 00:14:23 +08:00
|
|
|
err = pthread_attr_setstacksize(&attr,
|
|
|
|
(size_t) max(16 * 1024, PTHREAD_STACK_MIN));
|
2009-09-11 18:12:54 +08:00
|
|
|
BUG_ON(err);
|
|
|
|
err = pthread_mutex_lock(&start_work_mutex);
|
|
|
|
BUG_ON(err);
|
|
|
|
err = pthread_mutex_lock(&work_done_wait_mutex);
|
|
|
|
BUG_ON(err);
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task = tasks[i];
|
|
|
|
sem_init(&task->sleep_sem, 0, 0);
|
|
|
|
sem_init(&task->ready_for_work, 0, 0);
|
|
|
|
sem_init(&task->work_done_sem, 0, 0);
|
|
|
|
task->curr_event = 0;
|
|
|
|
err = pthread_create(&task->thread, &attr, thread_func, task);
|
|
|
|
BUG_ON(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wait_for_tasks(void)
|
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 cpu_usage_0, cpu_usage_1;
|
2009-09-11 18:12:54 +08:00
|
|
|
struct task_desc *task;
|
|
|
|
unsigned long i, ret;
|
|
|
|
|
|
|
|
start_time = get_nsecs();
|
|
|
|
cpu_usage = 0;
|
|
|
|
pthread_mutex_unlock(&work_done_wait_mutex);
|
|
|
|
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task = tasks[i];
|
|
|
|
ret = sem_wait(&task->ready_for_work);
|
|
|
|
BUG_ON(ret);
|
|
|
|
sem_init(&task->ready_for_work, 0, 0);
|
|
|
|
}
|
|
|
|
ret = pthread_mutex_lock(&work_done_wait_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
|
|
|
|
cpu_usage_0 = get_cpu_usage_nsec_parent();
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&start_work_mutex);
|
|
|
|
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task = tasks[i];
|
|
|
|
ret = sem_wait(&task->work_done_sem);
|
|
|
|
BUG_ON(ret);
|
|
|
|
sem_init(&task->work_done_sem, 0, 0);
|
|
|
|
cpu_usage += task->cpu_usage;
|
|
|
|
task->cpu_usage = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu_usage_1 = get_cpu_usage_nsec_parent();
|
|
|
|
if (!runavg_cpu_usage)
|
|
|
|
runavg_cpu_usage = cpu_usage;
|
|
|
|
runavg_cpu_usage = (runavg_cpu_usage*9 + cpu_usage)/10;
|
|
|
|
|
|
|
|
parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
|
|
|
|
if (!runavg_parent_cpu_usage)
|
|
|
|
runavg_parent_cpu_usage = parent_cpu_usage;
|
|
|
|
runavg_parent_cpu_usage = (runavg_parent_cpu_usage*9 +
|
|
|
|
parent_cpu_usage)/10;
|
|
|
|
|
|
|
|
ret = pthread_mutex_lock(&start_work_mutex);
|
|
|
|
BUG_ON(ret);
|
|
|
|
|
|
|
|
for (i = 0; i < nr_tasks; i++) {
|
|
|
|
task = tasks[i];
|
|
|
|
sem_init(&task->sleep_sem, 0, 0);
|
|
|
|
task->curr_event = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void run_one_test(void)
|
|
|
|
{
|
2011-01-25 00:13:04 +08:00
|
|
|
u64 T0, T1, delta, avg_delta, fluct;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
T0 = get_nsecs();
|
|
|
|
wait_for_tasks();
|
|
|
|
T1 = get_nsecs();
|
|
|
|
|
|
|
|
delta = T1 - T0;
|
|
|
|
sum_runtime += delta;
|
|
|
|
nr_runs++;
|
|
|
|
|
|
|
|
avg_delta = sum_runtime / nr_runs;
|
|
|
|
if (delta < avg_delta)
|
|
|
|
fluct = avg_delta - delta;
|
|
|
|
else
|
|
|
|
fluct = delta - avg_delta;
|
|
|
|
sum_fluct += fluct;
|
|
|
|
if (!run_avg)
|
|
|
|
run_avg = delta;
|
|
|
|
run_avg = (run_avg*9 + delta)/10;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
printf("#%-3ld: %0.3f, ",
|
2009-09-11 18:12:54 +08:00
|
|
|
nr_runs, (double)delta/1000000.0);
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
printf("ravg: %0.2f, ",
|
2009-09-11 18:12:54 +08:00
|
|
|
(double)run_avg/1e6);
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
printf("cpu: %0.2f / %0.2f",
|
2009-09-11 18:12:54 +08:00
|
|
|
(double)cpu_usage/1e6, (double)runavg_cpu_usage/1e6);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
* rusage statistics done by the parent, these are less
|
|
|
|
* accurate than the sum_exec_runtime based statistics:
|
|
|
|
*/
|
2009-09-11 18:12:54 +08:00
|
|
|
printf(" [%0.2f / %0.2f]",
|
2009-09-11 18:12:54 +08:00
|
|
|
(double)parent_cpu_usage/1e6,
|
|
|
|
(double)runavg_parent_cpu_usage/1e6);
|
|
|
|
#endif
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
printf("\n");
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
if (nr_sleep_corrections)
|
2009-09-11 18:12:54 +08:00
|
|
|
printf(" (%ld sleep corrections)\n", nr_sleep_corrections);
|
2009-09-11 18:12:54 +08:00
|
|
|
nr_sleep_corrections = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_calibrations(void)
|
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
u64 T0, T1;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
T0 = get_nsecs();
|
|
|
|
burn_nsecs(1e6);
|
|
|
|
T1 = get_nsecs();
|
|
|
|
|
2011-01-23 06:37:02 +08:00
|
|
|
printf("the run test took %" PRIu64 " nsecs\n", T1 - T0);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
T0 = get_nsecs();
|
|
|
|
sleep_nsecs(1e6);
|
|
|
|
T1 = get_nsecs();
|
|
|
|
|
2011-01-23 06:37:02 +08:00
|
|
|
printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0);
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2009-09-12 08:43:45 +08:00
|
|
|
#define FILL_FIELD(ptr, field, event, data) \
|
|
|
|
ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data)
|
|
|
|
|
|
|
|
#define FILL_ARRAY(ptr, array, event, data) \
|
|
|
|
do { \
|
|
|
|
void *__array = raw_field_ptr(event, #array, data); \
|
|
|
|
memcpy(ptr.array, __array, sizeof(ptr.array)); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define FILL_COMMON_FIELDS(ptr, event, data) \
|
|
|
|
do { \
|
|
|
|
FILL_FIELD(ptr, common_type, event, data); \
|
|
|
|
FILL_FIELD(ptr, common_flags, event, data); \
|
|
|
|
FILL_FIELD(ptr, common_preempt_count, event, data); \
|
|
|
|
FILL_FIELD(ptr, common_pid, event, data); \
|
|
|
|
FILL_FIELD(ptr, common_tgid, event, data); \
|
|
|
|
} while (0)
|
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
struct trace_switch_event {
|
|
|
|
u32 size;
|
|
|
|
|
|
|
|
u16 common_type;
|
|
|
|
u8 common_flags;
|
|
|
|
u8 common_preempt_count;
|
|
|
|
u32 common_pid;
|
|
|
|
u32 common_tgid;
|
|
|
|
|
|
|
|
char prev_comm[16];
|
|
|
|
u32 prev_pid;
|
|
|
|
u32 prev_prio;
|
|
|
|
u64 prev_state;
|
|
|
|
char next_comm[16];
|
|
|
|
u32 next_pid;
|
|
|
|
u32 next_prio;
|
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
struct trace_runtime_event {
|
|
|
|
u32 size;
|
|
|
|
|
|
|
|
u16 common_type;
|
|
|
|
u8 common_flags;
|
|
|
|
u8 common_preempt_count;
|
|
|
|
u32 common_pid;
|
|
|
|
u32 common_tgid;
|
|
|
|
|
|
|
|
char comm[16];
|
|
|
|
u32 pid;
|
|
|
|
u64 runtime;
|
|
|
|
u64 vruntime;
|
|
|
|
};
|
2009-09-12 09:59:01 +08:00
|
|
|
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
struct trace_wakeup_event {
|
|
|
|
u32 size;
|
|
|
|
|
|
|
|
u16 common_type;
|
|
|
|
u8 common_flags;
|
|
|
|
u8 common_preempt_count;
|
|
|
|
u32 common_pid;
|
|
|
|
u32 common_tgid;
|
|
|
|
|
|
|
|
char comm[16];
|
|
|
|
u32 pid;
|
|
|
|
|
|
|
|
u32 prio;
|
|
|
|
u32 success;
|
|
|
|
u32 cpu;
|
|
|
|
};
|
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
struct trace_fork_event {
|
|
|
|
u32 size;
|
2009-09-12 08:43:45 +08:00
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
u16 common_type;
|
|
|
|
u8 common_flags;
|
|
|
|
u8 common_preempt_count;
|
|
|
|
u32 common_pid;
|
|
|
|
u32 common_tgid;
|
|
|
|
|
|
|
|
char parent_comm[16];
|
|
|
|
u32 parent_pid;
|
|
|
|
char child_comm[16];
|
|
|
|
u32 child_pid;
|
|
|
|
};
|
|
|
|
|
2009-10-10 20:46:04 +08:00
|
|
|
struct trace_migrate_task_event {
|
|
|
|
u32 size;
|
|
|
|
|
|
|
|
u16 common_type;
|
|
|
|
u8 common_flags;
|
|
|
|
u8 common_preempt_count;
|
|
|
|
u32 common_pid;
|
|
|
|
u32 common_tgid;
|
|
|
|
|
|
|
|
char comm[16];
|
|
|
|
u32 pid;
|
|
|
|
|
|
|
|
u32 prio;
|
|
|
|
u32 cpu;
|
|
|
|
};
|
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
struct trace_sched_handler {
|
2012-09-09 09:53:06 +08:00
|
|
|
int (*switch_event)(struct trace_switch_event *event,
|
|
|
|
struct machine *machine,
|
|
|
|
struct event_format *tp_format,
|
|
|
|
struct perf_sample *sample);
|
2009-09-15 02:04:48 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
int (*runtime_event)(struct trace_runtime_event *event,
|
|
|
|
struct machine *machine,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct perf_sample *sample);
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
int (*wakeup_event)(struct trace_wakeup_event *event,
|
|
|
|
struct machine *machine,
|
|
|
|
struct event_format *tp_format,
|
|
|
|
struct perf_sample *sample);
|
2009-10-10 20:46:04 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
int (*fork_event)(struct trace_fork_event *event,
|
|
|
|
struct event_format *tp_format);
|
|
|
|
|
|
|
|
int (*migrate_task_event)(struct trace_migrate_task_event *event,
|
|
|
|
struct machine *machine,
|
|
|
|
struct perf_sample *sample);
|
2009-09-12 09:59:01 +08:00
|
|
|
};
|
2009-09-12 08:43:45 +08:00
|
|
|
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 09:59:01 +08:00
|
|
|
replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
|
2011-11-28 17:56:39 +08:00
|
|
|
struct machine *machine __used,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct event_format *event, struct perf_sample *sample)
|
2009-09-12 09:59:01 +08:00
|
|
|
{
|
|
|
|
struct task_desc *waker, *wakee;
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (verbose) {
|
|
|
|
printf("sched_wakeup event %p\n", event);
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
printf(" ... pid %d woke up %s/%d\n",
|
2009-09-12 09:59:01 +08:00
|
|
|
wakeup_event->common_pid,
|
|
|
|
wakeup_event->comm,
|
|
|
|
wakeup_event->pid);
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
waker = register_pid(wakeup_event->common_pid, "<unknown>");
|
|
|
|
wakee = register_pid(wakeup_event->pid, wakeup_event->comm);
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2012-08-07 22:33:42 +08:00
|
|
|
add_sched_event_wakeup(waker, sample->time, wakee);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 00:22:53 +08:00
|
|
|
static u64 cpu_last_switched[MAX_CPUS];
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 09:59:01 +08:00
|
|
|
replay_switch_event(struct trace_switch_event *switch_event,
|
2011-11-28 17:56:39 +08:00
|
|
|
struct machine *machine __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct perf_sample *sample)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2011-01-25 00:13:04 +08:00
|
|
|
struct task_desc *prev, __used *next;
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp0, timestamp = sample->time;
|
|
|
|
int cpu = sample->cpu;
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
s64 delta;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (verbose)
|
|
|
|
printf("sched_switch event %p\n", event);
|
|
|
|
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
if (cpu >= MAX_CPUS || cpu < 0)
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
timestamp0 = cpu_last_switched[cpu];
|
|
|
|
if (timestamp0)
|
|
|
|
delta = timestamp - timestamp0;
|
|
|
|
else
|
|
|
|
delta = 0;
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
if (delta < 0) {
|
|
|
|
pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta);
|
|
|
|
return -1;
|
|
|
|
}
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (verbose) {
|
2011-01-23 06:37:02 +08:00
|
|
|
printf(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n",
|
2009-09-12 09:59:01 +08:00
|
|
|
switch_event->prev_comm, switch_event->prev_pid,
|
|
|
|
switch_event->next_comm, switch_event->next_pid,
|
2009-09-11 18:12:54 +08:00
|
|
|
delta);
|
|
|
|
}
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
prev = register_pid(switch_event->prev_pid, switch_event->prev_comm);
|
|
|
|
next = register_pid(switch_event->next_pid, switch_event->next_comm);
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
cpu_last_switched[cpu] = timestamp;
|
|
|
|
|
|
|
|
add_sched_event_run(prev, timestamp, delta);
|
2009-09-12 09:59:01 +08:00
|
|
|
add_sched_event_sleep(prev, timestamp, switch_event->prev_state);
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 09:59:01 +08:00
|
|
|
replay_fork_event(struct trace_fork_event *fork_event,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct event_format *event)
|
2009-09-12 09:59:01 +08:00
|
|
|
{
|
|
|
|
if (verbose) {
|
|
|
|
printf("sched_fork event %p\n", event);
|
|
|
|
printf("... parent: %s/%d\n", fork_event->parent_comm, fork_event->parent_pid);
|
|
|
|
printf("... child: %s/%d\n", fork_event->child_comm, fork_event->child_pid);
|
|
|
|
}
|
|
|
|
register_pid(fork_event->parent_pid, fork_event->parent_comm);
|
|
|
|
register_pid(fork_event->child_pid, fork_event->child_comm);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 09:59:01 +08:00
|
|
|
}
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
static struct trace_sched_handler replay_ops = {
|
2009-09-12 16:08:34 +08:00
|
|
|
.wakeup_event = replay_wakeup_event,
|
|
|
|
.switch_event = replay_switch_event,
|
|
|
|
.fork_event = replay_fork_event,
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
};
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
struct sort_dimension {
|
|
|
|
const char *name;
|
2009-09-11 18:12:54 +08:00
|
|
|
sort_fn_t cmp;
|
2009-09-11 18:12:54 +08:00
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
|
|
|
static LIST_HEAD(cmp_pid);
|
|
|
|
|
2009-09-13 09:36:29 +08:00
|
|
|
static int
|
2009-09-15 02:04:48 +08:00
|
|
|
thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
struct sort_dimension *sort;
|
|
|
|
int ret = 0;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
BUG_ON(list_empty(list));
|
|
|
|
|
2009-09-13 09:36:29 +08:00
|
|
|
list_for_each_entry(sort, list, list) {
|
|
|
|
ret = sort->cmp(l, r);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static struct work_atoms *
|
2009-09-11 18:12:54 +08:00
|
|
|
thread_atoms_search(struct rb_root *root, struct thread *thread,
|
|
|
|
struct list_head *sort_list)
|
|
|
|
{
|
|
|
|
struct rb_node *node = root->rb_node;
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms key = { .thread = thread };
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
while (node) {
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms *atoms;
|
2009-09-11 18:12:54 +08:00
|
|
|
int cmp;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
atoms = container_of(node, struct work_atoms, node);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
cmp = thread_lat_cmp(sort_list, &key, atoms);
|
|
|
|
if (cmp > 0)
|
|
|
|
node = node->rb_left;
|
|
|
|
else if (cmp < 0)
|
|
|
|
node = node->rb_right;
|
|
|
|
else {
|
|
|
|
BUG_ON(thread != atoms->thread);
|
|
|
|
return atoms;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-09-12 14:06:14 +08:00
|
|
|
static void
|
2009-09-15 02:04:48 +08:00
|
|
|
__thread_latency_insert(struct rb_root *root, struct work_atoms *data,
|
2009-09-13 09:36:29 +08:00
|
|
|
struct list_head *sort_list)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
|
|
|
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
|
|
|
|
|
|
|
while (*new) {
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms *this;
|
2009-09-13 09:36:29 +08:00
|
|
|
int cmp;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
this = container_of(*new, struct work_atoms, node);
|
2009-09-12 14:06:14 +08:00
|
|
|
parent = *new;
|
2009-09-13 09:36:29 +08:00
|
|
|
|
|
|
|
cmp = thread_lat_cmp(sort_list, data, this);
|
|
|
|
|
|
|
|
if (cmp > 0)
|
2009-09-12 14:06:14 +08:00
|
|
|
new = &((*new)->rb_left);
|
|
|
|
else
|
2009-09-13 09:36:29 +08:00
|
|
|
new = &((*new)->rb_right);
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
rb_link_node(&data->node, parent, new);
|
|
|
|
rb_insert_color(&data->node, root);
|
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int thread_atoms_insert(struct thread *thread)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
2009-11-24 22:05:16 +08:00
|
|
|
struct work_atoms *atoms = zalloc(sizeof(*atoms));
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!atoms) {
|
|
|
|
pr_err("No memory at %s\n", __func__);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-13 05:11:32 +08:00
|
|
|
atoms->thread = thread;
|
2009-09-15 02:04:48 +08:00
|
|
|
INIT_LIST_HEAD(&atoms->work_list);
|
2009-09-11 18:12:54 +08:00
|
|
|
__thread_latency_insert(&atom_root, atoms, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 14:06:14 +08:00
|
|
|
latency_fork_event(struct trace_fork_event *fork_event __used,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct event_format *event __used)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
|
|
|
/* should insert the newcomer */
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-12 16:08:34 +08:00
|
|
|
__used
|
2009-09-12 14:06:14 +08:00
|
|
|
static char sched_out_state(struct trace_switch_event *switch_event)
|
|
|
|
{
|
|
|
|
const char *str = TASK_STATE_TO_CHAR_STR;
|
|
|
|
|
|
|
|
return str[switch_event->prev_state];
|
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-15 02:04:48 +08:00
|
|
|
add_sched_out_event(struct work_atoms *atoms,
|
|
|
|
char run_state,
|
|
|
|
u64 timestamp)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
2009-11-24 22:05:16 +08:00
|
|
|
struct work_atom *atom = zalloc(sizeof(*atom));
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!atom) {
|
|
|
|
pr_err("Non memory at %s", __func__);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-12 14:06:14 +08:00
|
|
|
|
perf tools: Fix processing of randomly serialized sched traces
Currently it's possible to meet such too high latency results
with 'perf sched latency'.
-----------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------
xfce4-panel | 0.222 ms | 2 | avg: 4718.345 ms | max: 9436.493 ms |
scsi_eh_3 | 3.962 ms | 36 | avg: 55.957 ms | max: 1977.829 ms |
The origin is on traces that are sometimes badly serialized across cpus.
For example the raw traces that raised such results for xfce4-panel:
(1) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(2) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(3) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
The traces are processed in the order they arrive. Then in (2),
xfce4-panel sleeps, it is first waken up in (3) and eventually
scheduled in (5).
The latency reported is then 1504 - 1495 = 9 secs, as reported by perf
sched. But this is wrong, we are confident in the fact the traces are
nicely serialized while we should actually more trust the timestamps.
If we reorder by timestamps we get:
(1) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(2) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(3) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
Now the trace make more sense, xfce4-panel is sleeping. Then it is
woken up in (1), scheduled in (2)
It goes to sleep in (3), woken up in (4) and scheduled in (5).
Now, latency captured between (1) and (2) is of 39 us.
And between (4) and (5) it is 2.1 ms.
Such pattern of bad serializing is the origin of the high latencies
reported by perf sched.
Basically, we need to check whether wake up time is higher than
schedule out time. If it's not the case, we need to tag the current
work atom as invalid.
Beside that, we may need to work later on a better ordering of the
traces given by the kernel.
After this patch:
xfce4-session | 0.221 ms | 1 | avg: 0.538 ms | max: 0.538 ms |
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-14 09:01:12 +08:00
|
|
|
atom->sched_out_time = timestamp;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
if (run_state == 'R') {
|
2009-09-11 18:12:54 +08:00
|
|
|
atom->state = THREAD_WAIT_CPU;
|
perf tools: Fix processing of randomly serialized sched traces
Currently it's possible to meet such too high latency results
with 'perf sched latency'.
-----------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------
xfce4-panel | 0.222 ms | 2 | avg: 4718.345 ms | max: 9436.493 ms |
scsi_eh_3 | 3.962 ms | 36 | avg: 55.957 ms | max: 1977.829 ms |
The origin is on traces that are sometimes badly serialized across cpus.
For example the raw traces that raised such results for xfce4-panel:
(1) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(2) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(3) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
The traces are processed in the order they arrive. Then in (2),
xfce4-panel sleeps, it is first waken up in (3) and eventually
scheduled in (5).
The latency reported is then 1504 - 1495 = 9 secs, as reported by perf
sched. But this is wrong, we are confident in the fact the traces are
nicely serialized while we should actually more trust the timestamps.
If we reorder by timestamps we get:
(1) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(2) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(3) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
Now the trace make more sense, xfce4-panel is sleeping. Then it is
woken up in (1), scheduled in (2)
It goes to sleep in (3), woken up in (4) and scheduled in (5).
Now, latency captured between (1) and (2) is of 39 us.
And between (4) and (5) it is 2.1 ms.
Such pattern of bad serializing is the origin of the high latencies
reported by perf sched.
Basically, we need to check whether wake up time is higher than
schedule out time. If it's not the case, we need to tag the current
work atom as invalid.
Beside that, we may need to work later on a better ordering of the
traces given by the kernel.
After this patch:
xfce4-session | 0.221 ms | 1 | avg: 0.538 ms | max: 0.538 ms |
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-14 09:01:12 +08:00
|
|
|
atom->wake_up_time = atom->sched_out_time;
|
2009-09-13 06:46:19 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
list_add_tail(&atom->list, &atoms->work_list);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-15 02:04:48 +08:00
|
|
|
add_runtime_event(struct work_atoms *atoms, u64 delta, u64 timestamp __used)
|
|
|
|
{
|
|
|
|
struct work_atom *atom;
|
|
|
|
|
|
|
|
BUG_ON(list_empty(&atoms->work_list));
|
|
|
|
|
|
|
|
atom = list_entry(atoms->work_list.prev, struct work_atom, list);
|
|
|
|
|
|
|
|
atom->runtime += delta;
|
|
|
|
atoms->total_runtime += delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
struct work_atom *atom;
|
2009-09-13 07:56:25 +08:00
|
|
|
u64 delta;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
if (list_empty(&atoms->work_list))
|
2009-09-12 14:06:14 +08:00
|
|
|
return;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
atom = list_entry(atoms->work_list.prev, struct work_atom, list);
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (atom->state != THREAD_WAIT_CPU)
|
2009-09-12 14:06:14 +08:00
|
|
|
return;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
if (timestamp < atom->wake_up_time) {
|
|
|
|
atom->state = THREAD_IGNORE;
|
2009-09-12 14:06:14 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
atom->state = THREAD_SCHED_IN;
|
|
|
|
atom->sched_in_time = timestamp;
|
2009-09-13 07:56:25 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
delta = atom->sched_in_time - atom->wake_up_time;
|
2009-09-13 07:56:25 +08:00
|
|
|
atoms->total_lat += delta;
|
2009-12-10 04:40:08 +08:00
|
|
|
if (delta > atoms->max_lat) {
|
2009-09-13 07:56:25 +08:00
|
|
|
atoms->max_lat = delta;
|
2009-12-10 04:40:08 +08:00
|
|
|
atoms->max_lat_at = timestamp;
|
|
|
|
}
|
2009-09-13 07:56:25 +08:00
|
|
|
atoms->nb_atoms++;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 14:06:14 +08:00
|
|
|
latency_switch_event(struct trace_switch_event *switch_event,
|
2011-11-28 17:56:39 +08:00
|
|
|
struct machine *machine,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event __used,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct perf_sample *sample)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms *out_events, *in_events;
|
2009-09-12 14:06:14 +08:00
|
|
|
struct thread *sched_out, *sched_in;
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp0, timestamp = sample->time;
|
|
|
|
int cpu = sample->cpu;
|
2009-09-12 16:08:34 +08:00
|
|
|
s64 delta;
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
BUG_ON(cpu >= MAX_CPUS || cpu < 0);
|
2009-09-12 16:08:34 +08:00
|
|
|
|
|
|
|
timestamp0 = cpu_last_switched[cpu];
|
|
|
|
cpu_last_switched[cpu] = timestamp;
|
|
|
|
if (timestamp0)
|
|
|
|
delta = timestamp - timestamp0;
|
|
|
|
else
|
|
|
|
delta = 0;
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
if (delta < 0) {
|
|
|
|
pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2011-11-28 17:56:39 +08:00
|
|
|
sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
|
|
|
|
sched_in = machine__findnew_thread(machine, switch_event->next_pid);
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
|
|
|
|
if (!out_events) {
|
2012-09-09 09:53:06 +08:00
|
|
|
if (thread_atoms_insert(sched_out))
|
|
|
|
return -1;
|
2009-09-15 02:04:48 +08:00
|
|
|
out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!out_events) {
|
|
|
|
pr_err("out-event: Internal tree error");
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-15 02:04:48 +08:00
|
|
|
}
|
2012-09-09 09:53:06 +08:00
|
|
|
if (add_sched_out_event(out_events, sched_out_state(switch_event), timestamp))
|
|
|
|
return -1;
|
2009-09-15 02:04:48 +08:00
|
|
|
|
|
|
|
in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid);
|
|
|
|
if (!in_events) {
|
2012-09-09 09:53:06 +08:00
|
|
|
if (thread_atoms_insert(sched_in))
|
|
|
|
return -1;
|
2009-09-15 02:04:48 +08:00
|
|
|
in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!in_events) {
|
|
|
|
pr_err("in-event: Internal tree error");
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-15 02:04:48 +08:00
|
|
|
/*
|
|
|
|
* Take came in we have not heard about yet,
|
|
|
|
* add in an initial atom in runnable state:
|
|
|
|
*/
|
2012-09-09 09:53:06 +08:00
|
|
|
if (add_sched_out_event(in_events, 'R', timestamp))
|
|
|
|
return -1;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
2009-09-15 02:04:48 +08:00
|
|
|
add_sched_in_event(in_events, timestamp);
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
2009-09-15 02:04:48 +08:00
|
|
|
}
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-15 02:04:48 +08:00
|
|
|
latency_runtime_event(struct trace_runtime_event *runtime_event,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct machine *machine, struct perf_sample *sample)
|
2009-09-15 02:04:48 +08:00
|
|
|
{
|
2011-11-28 17:56:39 +08:00
|
|
|
struct thread *thread = machine__findnew_thread(machine, runtime_event->pid);
|
2009-10-13 22:16:29 +08:00
|
|
|
struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp = sample->time;
|
|
|
|
int cpu = sample->cpu;
|
2009-09-15 02:04:48 +08:00
|
|
|
|
|
|
|
BUG_ON(cpu >= MAX_CPUS || cpu < 0);
|
|
|
|
if (!atoms) {
|
2012-09-09 09:53:06 +08:00
|
|
|
if (thread_atoms_insert(thread))
|
|
|
|
return -1;
|
2009-09-15 02:04:48 +08:00
|
|
|
atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!atoms) {
|
|
|
|
pr_debug("in-event: Internal tree error");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (add_sched_out_event(atoms, 'R', timestamp))
|
|
|
|
return -1;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
add_runtime_event(atoms, runtime_event->runtime, timestamp);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-12 14:06:14 +08:00
|
|
|
latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct machine *machine, struct event_format *event __used,
|
|
|
|
struct perf_sample *sample)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms *atoms;
|
2009-09-11 18:12:54 +08:00
|
|
|
struct work_atom *atom;
|
2009-09-12 14:06:14 +08:00
|
|
|
struct thread *wakee;
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp = sample->time;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
|
|
|
/* Note for later, it may be interesting to observe the failing cases */
|
|
|
|
if (!wakeup_event->success)
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2011-11-28 17:56:39 +08:00
|
|
|
wakee = machine__findnew_thread(machine, wakeup_event->pid);
|
2009-09-11 18:12:54 +08:00
|
|
|
atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
|
2009-09-13 05:11:32 +08:00
|
|
|
if (!atoms) {
|
2012-09-09 09:53:06 +08:00
|
|
|
if (thread_atoms_insert(wakee))
|
|
|
|
return -1;
|
2009-09-15 02:04:48 +08:00
|
|
|
atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!atoms) {
|
|
|
|
pr_debug("wakeup-event: Internal tree error");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (add_sched_out_event(atoms, 'S', timestamp))
|
|
|
|
return -1;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
BUG_ON(list_empty(&atoms->work_list));
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
atom = list_entry(atoms->work_list.prev, struct work_atom, list);
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-10-10 20:46:04 +08:00
|
|
|
/*
|
|
|
|
* You WILL be missing events if you've recorded only
|
|
|
|
* one CPU, or are only looking at only one, so don't
|
|
|
|
* make useless noise.
|
|
|
|
*/
|
|
|
|
if (profile_cpu == -1 && atom->state != THREAD_SLEEPING)
|
2009-09-16 19:45:00 +08:00
|
|
|
nr_state_machine_bugs++;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-14 00:15:54 +08:00
|
|
|
nr_timestamps++;
|
|
|
|
if (atom->sched_out_time > timestamp) {
|
2009-09-16 19:45:00 +08:00
|
|
|
nr_unordered_timestamps++;
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-14 00:15:54 +08:00
|
|
|
}
|
perf tools: Fix processing of randomly serialized sched traces
Currently it's possible to meet such too high latency results
with 'perf sched latency'.
-----------------------------------------------------------------------------------
Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |
-----------------------------------------------------------------------------------
xfce4-panel | 0.222 ms | 2 | avg: 4718.345 ms | max: 9436.493 ms |
scsi_eh_3 | 3.962 ms | 36 | avg: 55.957 ms | max: 1977.829 ms |
The origin is on traces that are sometimes badly serialized across cpus.
For example the raw traces that raised such results for xfce4-panel:
(1) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(2) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(3) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
The traces are processed in the order they arrive. Then in (2),
xfce4-panel sleeps, it is first waken up in (3) and eventually
scheduled in (5).
The latency reported is then 1504 - 1495 = 9 secs, as reported by perf
sched. But this is wrong, we are confident in the fact the traces are
nicely serialized while we should actually more trust the timestamps.
If we reorder by timestamps we get:
(1) Xorg-4276 [001] 1494.663860125: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(2) [init]-0 [000] 1494.663899990: sched_switch: task swapper:0 [140] (R) ==> xfce4-panel:4569 [120]
(3) xfce4-panel-4569 [000] 1494.663928373: sched_switch: task xfce4-panel:4569 [120] (S) ==> swapper:0 [140]
(4) Xorg-4276 [001] 1504.098252756: sched_wakeup: task xfce4-panel:4569 [120] success=1 [000]
(5) perf-5219 [000] 1504.100353302: sched_switch: task perf:5219 [120] (S) ==> xfce4-panel:4569 [120]
Now the trace make more sense, xfce4-panel is sleeping. Then it is
woken up in (1), scheduled in (2)
It goes to sleep in (3), woken up in (4) and scheduled in (5).
Now, latency captured between (1) and (2) is of 39 us.
And between (4) and (5) it is 2.1 ms.
Such pattern of bad serializing is the origin of the high latencies
reported by perf sched.
Basically, we need to check whether wake up time is higher than
schedule out time. If it's not the case, we need to tag the current
work atom as invalid.
Beside that, we may need to work later on a better ordering of the
traces given by the kernel.
After this patch:
xfce4-session | 0.221 ms | 1 | avg: 0.538 ms | max: 0.538 ms |
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-14 09:01:12 +08:00
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
atom->state = THREAD_WAIT_CPU;
|
|
|
|
atom->wake_up_time = timestamp;
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-10-10 20:46:04 +08:00
|
|
|
latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct machine *machine, struct perf_sample *sample)
|
2009-10-10 20:46:04 +08:00
|
|
|
{
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp = sample->time;
|
2009-10-10 20:46:04 +08:00
|
|
|
struct work_atoms *atoms;
|
|
|
|
struct work_atom *atom;
|
|
|
|
struct thread *migrant;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only need to worry about migration when profiling one CPU.
|
|
|
|
*/
|
|
|
|
if (profile_cpu == -1)
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-10-10 20:46:04 +08:00
|
|
|
|
2011-11-28 17:56:39 +08:00
|
|
|
migrant = machine__findnew_thread(machine, migrate_task_event->pid);
|
2009-10-10 20:46:04 +08:00
|
|
|
atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
|
|
|
|
if (!atoms) {
|
2012-09-09 09:53:06 +08:00
|
|
|
if (thread_atoms_insert(migrant))
|
|
|
|
return -1;
|
2009-10-10 20:46:04 +08:00
|
|
|
register_pid(migrant->pid, migrant->comm);
|
|
|
|
atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (!atoms) {
|
|
|
|
pr_debug("migration-event: Internal tree error");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (add_sched_out_event(atoms, 'R', timestamp))
|
|
|
|
return -1;
|
2009-10-10 20:46:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BUG_ON(list_empty(&atoms->work_list));
|
|
|
|
|
|
|
|
atom = list_entry(atoms->work_list.prev, struct work_atom, list);
|
|
|
|
atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp;
|
|
|
|
|
|
|
|
nr_timestamps++;
|
|
|
|
|
|
|
|
if (atom->sched_out_time > timestamp)
|
|
|
|
nr_unordered_timestamps++;
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
2009-10-10 20:46:04 +08:00
|
|
|
}
|
|
|
|
|
2009-09-12 14:06:14 +08:00
|
|
|
static struct trace_sched_handler lat_ops = {
|
2009-09-12 16:08:34 +08:00
|
|
|
.wakeup_event = latency_wakeup_event,
|
|
|
|
.switch_event = latency_switch_event,
|
2009-09-15 02:04:48 +08:00
|
|
|
.runtime_event = latency_runtime_event,
|
2009-09-12 16:08:34 +08:00
|
|
|
.fork_event = latency_fork_event,
|
2009-10-10 20:46:04 +08:00
|
|
|
.migrate_task_event = latency_migrate_task_event,
|
2009-09-12 14:06:14 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static void output_lat_thread(struct work_atoms *work_list)
|
2009-09-12 14:06:14 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int ret;
|
2009-09-13 07:56:25 +08:00
|
|
|
u64 avg;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
if (!work_list->nb_atoms)
|
2009-09-12 14:06:14 +08:00
|
|
|
return;
|
2009-09-14 00:15:54 +08:00
|
|
|
/*
|
|
|
|
* Ignore idle threads:
|
|
|
|
*/
|
2009-09-16 20:12:36 +08:00
|
|
|
if (!strcmp(work_list->thread->comm, "swapper"))
|
2009-09-14 00:15:54 +08:00
|
|
|
return;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
all_runtime += work_list->total_runtime;
|
|
|
|
all_count += work_list->nb_atoms;
|
2009-09-13 07:56:25 +08:00
|
|
|
|
2009-09-16 20:12:36 +08:00
|
|
|
ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->pid);
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2009-09-15 00:30:44 +08:00
|
|
|
for (i = 0; i < 24 - ret; i++)
|
2009-09-12 14:06:14 +08:00
|
|
|
printf(" ");
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
avg = work_list->total_lat / work_list->nb_atoms;
|
2009-09-12 14:06:14 +08:00
|
|
|
|
2011-01-23 06:37:02 +08:00
|
|
|
printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n",
|
2009-09-15 02:04:48 +08:00
|
|
|
(double)work_list->total_runtime / 1e6,
|
|
|
|
work_list->nb_atoms, (double)avg / 1e6,
|
2009-12-10 04:40:08 +08:00
|
|
|
(double)work_list->max_lat / 1e6,
|
|
|
|
(double)work_list->max_lat_at / 1e9);
|
2009-09-12 14:06:14 +08:00
|
|
|
}
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
if (l->thread->pid < r->thread->pid)
|
|
|
|
return -1;
|
|
|
|
if (l->thread->pid > r->thread->pid)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sort_dimension pid_sort_dimension = {
|
2009-09-11 18:12:54 +08:00
|
|
|
.name = "pid",
|
|
|
|
.cmp = pid_cmp,
|
2009-09-13 09:36:29 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static int avg_cmp(struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
u64 avgl, avgr;
|
|
|
|
|
|
|
|
if (!l->nb_atoms)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!r->nb_atoms)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
avgl = l->total_lat / l->nb_atoms;
|
|
|
|
avgr = r->total_lat / r->nb_atoms;
|
|
|
|
|
|
|
|
if (avgl < avgr)
|
|
|
|
return -1;
|
|
|
|
if (avgl > avgr)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sort_dimension avg_sort_dimension = {
|
2009-09-11 18:12:54 +08:00
|
|
|
.name = "avg",
|
|
|
|
.cmp = avg_cmp,
|
2009-09-13 09:36:29 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static int max_cmp(struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
if (l->max_lat < r->max_lat)
|
|
|
|
return -1;
|
|
|
|
if (l->max_lat > r->max_lat)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sort_dimension max_sort_dimension = {
|
2009-09-11 18:12:54 +08:00
|
|
|
.name = "max",
|
|
|
|
.cmp = max_cmp,
|
2009-09-13 09:36:29 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static int switch_cmp(struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
if (l->nb_atoms < r->nb_atoms)
|
|
|
|
return -1;
|
|
|
|
if (l->nb_atoms > r->nb_atoms)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sort_dimension switch_sort_dimension = {
|
2009-09-11 18:12:54 +08:00
|
|
|
.name = "switch",
|
|
|
|
.cmp = switch_cmp,
|
2009-09-13 09:36:29 +08:00
|
|
|
};
|
|
|
|
|
2009-09-15 02:04:48 +08:00
|
|
|
static int runtime_cmp(struct work_atoms *l, struct work_atoms *r)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
if (l->total_runtime < r->total_runtime)
|
|
|
|
return -1;
|
|
|
|
if (l->total_runtime > r->total_runtime)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sort_dimension runtime_sort_dimension = {
|
2009-09-11 18:12:54 +08:00
|
|
|
.name = "runtime",
|
|
|
|
.cmp = runtime_cmp,
|
2009-09-13 09:36:29 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct sort_dimension *available_sorts[] = {
|
|
|
|
&pid_sort_dimension,
|
|
|
|
&avg_sort_dimension,
|
|
|
|
&max_sort_dimension,
|
|
|
|
&switch_sort_dimension,
|
|
|
|
&runtime_sort_dimension,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define NB_AVAILABLE_SORTS (int)(sizeof(available_sorts) / sizeof(struct sort_dimension *))
|
|
|
|
|
|
|
|
static LIST_HEAD(sort_list);
|
|
|
|
|
2009-10-06 04:17:29 +08:00
|
|
|
static int sort_dimension__add(const char *tok, struct list_head *list)
|
2009-09-13 09:36:29 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NB_AVAILABLE_SORTS; i++) {
|
|
|
|
if (!strcmp(available_sorts[i]->name, tok)) {
|
|
|
|
list_add_tail(&available_sorts[i]->list, list);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setup_sorting(void);
|
|
|
|
|
|
|
|
static void sort_lat(void)
|
|
|
|
{
|
|
|
|
struct rb_node *node;
|
|
|
|
|
|
|
|
for (;;) {
|
2009-09-15 02:04:48 +08:00
|
|
|
struct work_atoms *data;
|
2009-09-11 18:12:54 +08:00
|
|
|
node = rb_first(&atom_root);
|
2009-09-13 09:36:29 +08:00
|
|
|
if (!node)
|
|
|
|
break;
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
rb_erase(node, &atom_root);
|
2009-09-15 02:04:48 +08:00
|
|
|
data = rb_entry(node, struct work_atoms, node);
|
2009-09-11 18:12:54 +08:00
|
|
|
__thread_latency_insert(&sorted_atom_root, data, &sort_list);
|
2009-09-13 09:36:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-12 09:59:01 +08:00
|
|
|
static struct trace_sched_handler *trace_handler;
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_wakeup_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct thread *thread __used)
|
2009-09-12 09:59:01 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
void *data = sample->raw_data;
|
2009-09-12 09:59:01 +08:00
|
|
|
struct trace_wakeup_event wakeup_event;
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = 0;
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_COMMON_FIELDS(wakeup_event, event, data);
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_ARRAY(wakeup_event, comm, event, data);
|
|
|
|
FILL_FIELD(wakeup_event, pid, event, data);
|
|
|
|
FILL_FIELD(wakeup_event, prio, event, data);
|
|
|
|
FILL_FIELD(wakeup_event, success, event, data);
|
|
|
|
FILL_FIELD(wakeup_event, cpu, event, data);
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
if (trace_handler->wakeup_event)
|
2012-09-09 09:53:06 +08:00
|
|
|
err = trace_handler->wakeup_event(&wakeup_event, machine, event, sample);
|
|
|
|
|
|
|
|
return err;
|
2009-09-12 09:59:01 +08:00
|
|
|
}
|
|
|
|
|
2009-09-16 20:07:00 +08:00
|
|
|
/*
|
|
|
|
* Track the current task - that way we can know whether there's any
|
|
|
|
* weird events, such as a task being switched away that is not current.
|
|
|
|
*/
|
2009-09-18 00:24:55 +08:00
|
|
|
static int max_cpu;
|
2009-09-16 23:40:48 +08:00
|
|
|
|
2009-09-16 20:07:00 +08:00
|
|
|
static u32 curr_pid[MAX_CPUS] = { [0 ... MAX_CPUS-1] = -1 };
|
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
static struct thread *curr_thread[MAX_CPUS];
|
|
|
|
|
|
|
|
static char next_shortname1 = 'A';
|
|
|
|
static char next_shortname2 = '0';
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
2009-09-16 23:40:48 +08:00
|
|
|
map_switch_event(struct trace_switch_event *switch_event,
|
2011-11-28 17:56:39 +08:00
|
|
|
struct machine *machine,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event __used,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct perf_sample *sample)
|
2009-09-16 23:40:48 +08:00
|
|
|
{
|
2011-01-25 00:13:04 +08:00
|
|
|
struct thread *sched_out __used, *sched_in;
|
2009-09-16 23:40:48 +08:00
|
|
|
int new_shortname;
|
2012-08-07 22:33:42 +08:00
|
|
|
u64 timestamp0, timestamp = sample->time;
|
2009-09-16 23:40:48 +08:00
|
|
|
s64 delta;
|
2012-08-07 22:33:42 +08:00
|
|
|
int cpu, this_cpu = sample->cpu;
|
2009-09-16 23:40:48 +08:00
|
|
|
|
|
|
|
BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);
|
|
|
|
|
|
|
|
if (this_cpu > max_cpu)
|
|
|
|
max_cpu = this_cpu;
|
|
|
|
|
|
|
|
timestamp0 = cpu_last_switched[this_cpu];
|
|
|
|
cpu_last_switched[this_cpu] = timestamp;
|
|
|
|
if (timestamp0)
|
|
|
|
delta = timestamp - timestamp0;
|
|
|
|
else
|
|
|
|
delta = 0;
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
if (delta < 0) {
|
|
|
|
pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-09-16 23:40:48 +08:00
|
|
|
|
2011-11-28 17:56:39 +08:00
|
|
|
sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
|
|
|
|
sched_in = machine__findnew_thread(machine, switch_event->next_pid);
|
2009-09-16 23:40:48 +08:00
|
|
|
|
|
|
|
curr_thread[this_cpu] = sched_in;
|
|
|
|
|
|
|
|
printf(" ");
|
|
|
|
|
|
|
|
new_shortname = 0;
|
|
|
|
if (!sched_in->shortname[0]) {
|
|
|
|
sched_in->shortname[0] = next_shortname1;
|
|
|
|
sched_in->shortname[1] = next_shortname2;
|
|
|
|
|
|
|
|
if (next_shortname1 < 'Z') {
|
|
|
|
next_shortname1++;
|
|
|
|
} else {
|
|
|
|
next_shortname1='A';
|
|
|
|
if (next_shortname2 < '9') {
|
|
|
|
next_shortname2++;
|
|
|
|
} else {
|
|
|
|
next_shortname2='0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
new_shortname = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cpu = 0; cpu <= max_cpu; cpu++) {
|
|
|
|
if (cpu != this_cpu)
|
|
|
|
printf(" ");
|
|
|
|
else
|
|
|
|
printf("*");
|
|
|
|
|
|
|
|
if (curr_thread[cpu]) {
|
|
|
|
if (curr_thread[cpu]->pid)
|
|
|
|
printf("%2s ", curr_thread[cpu]->shortname);
|
|
|
|
else
|
|
|
|
printf(". ");
|
|
|
|
} else
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" %12.6f secs ", (double)timestamp/1e9);
|
|
|
|
if (new_shortname) {
|
|
|
|
printf("%s => %s:%d\n",
|
|
|
|
sched_in->shortname, sched_in->comm, sched_in->pid);
|
|
|
|
} else {
|
|
|
|
printf("\n");
|
|
|
|
}
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
2009-09-16 23:40:48 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_switch_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct thread *thread __used)
|
2009-09-12 09:59:01 +08:00
|
|
|
{
|
2012-09-09 09:53:06 +08:00
|
|
|
int this_cpu = sample->cpu, err = 0;
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
void *data = sample->raw_data;
|
2009-09-12 09:59:01 +08:00
|
|
|
struct trace_switch_event switch_event;
|
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_COMMON_FIELDS(switch_event, event, data);
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_ARRAY(switch_event, prev_comm, event, data);
|
|
|
|
FILL_FIELD(switch_event, prev_pid, event, data);
|
|
|
|
FILL_FIELD(switch_event, prev_prio, event, data);
|
|
|
|
FILL_FIELD(switch_event, prev_state, event, data);
|
|
|
|
FILL_ARRAY(switch_event, next_comm, event, data);
|
|
|
|
FILL_FIELD(switch_event, next_pid, event, data);
|
|
|
|
FILL_FIELD(switch_event, next_prio, event, data);
|
2009-09-12 09:59:01 +08:00
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
if (curr_pid[this_cpu] != (u32)-1) {
|
2009-09-16 20:07:00 +08:00
|
|
|
/*
|
|
|
|
* Are we trying to switch away a PID that is
|
|
|
|
* not current?
|
|
|
|
*/
|
2009-09-16 23:40:48 +08:00
|
|
|
if (curr_pid[this_cpu] != switch_event.prev_pid)
|
2009-09-16 20:07:00 +08:00
|
|
|
nr_context_switch_bugs++;
|
|
|
|
}
|
2009-09-16 23:40:48 +08:00
|
|
|
if (trace_handler->switch_event)
|
2012-09-09 09:53:06 +08:00
|
|
|
err = trace_handler->switch_event(&switch_event, machine, event, sample);
|
2009-09-16 20:07:00 +08:00
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
curr_pid[this_cpu] = switch_event.next_pid;
|
2012-09-09 09:53:06 +08:00
|
|
|
return err;
|
2009-09-12 09:59:01 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_runtime_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct thread *thread __used)
|
2009-09-15 02:04:48 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
void *data = sample->raw_data;
|
2009-09-15 02:04:48 +08:00
|
|
|
struct trace_runtime_event runtime_event;
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = 0;
|
2009-09-15 02:04:48 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_ARRAY(runtime_event, comm, event, data);
|
|
|
|
FILL_FIELD(runtime_event, pid, event, data);
|
|
|
|
FILL_FIELD(runtime_event, runtime, event, data);
|
|
|
|
FILL_FIELD(runtime_event, vruntime, event, data);
|
2009-09-15 02:04:48 +08:00
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
if (trace_handler->runtime_event)
|
2012-09-09 09:53:06 +08:00
|
|
|
err = trace_handler->runtime_event(&runtime_event, machine, sample);
|
|
|
|
|
|
|
|
return err;
|
2009-09-15 02:04:48 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_fork_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine __used,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct thread *thread __used)
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
void *data = sample->raw_data;
|
2009-09-12 08:43:45 +08:00
|
|
|
struct trace_fork_event fork_event;
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = 0;
|
2009-09-12 08:43:45 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_COMMON_FIELDS(fork_event, event, data);
|
2009-09-12 08:43:45 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_ARRAY(fork_event, parent_comm, event, data);
|
|
|
|
FILL_FIELD(fork_event, parent_pid, event, data);
|
|
|
|
FILL_ARRAY(fork_event, child_comm, event, data);
|
|
|
|
FILL_FIELD(fork_event, child_pid, event, data);
|
2009-09-12 08:43:45 +08:00
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
if (trace_handler->fork_event)
|
2012-09-09 09:53:06 +08:00
|
|
|
err = trace_handler->fork_event(&fork_event, event);
|
|
|
|
|
|
|
|
return err;
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_exit_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample __used,
|
|
|
|
struct machine *machine __used,
|
2009-09-12 09:59:01 +08:00
|
|
|
struct thread *thread __used)
|
perf sched: Implement the scheduling workload replay engine
Integrate the schedbench.c bits with the raw trace events
that we get from the perf machinery, and activate the
workload replayer/simulator.
Example of a captured 'make -j' workload:
$ perf sched
run measurement overhead: 90 nsecs
sleep measurement overhead: 2724743 nsecs
the run test took 1000081 nsecs
the sleep test took 2981111 nsecs
version = 0.5
...
nr_run_events: 70
nr_sleep_events: 66
nr_wakeup_events: 9
target-less wakeups: 71
multi-target wakeups: 47
run events optimized: 139
task 0 ( perf: 6607), nr_events: 2
task 1 ( perf: 6608), nr_events: 6
task 2 ( : 0), nr_events: 1
task 3 ( make: 6609), nr_events: 5
task 4 ( sh: 6610), nr_events: 4
task 5 ( make: 6611), nr_events: 6
task 6 ( sh: 6612), nr_events: 4
task 7 ( make: 6613), nr_events: 5
task 8 ( migration/11: 25), nr_events: 1
task 9 ( migration/13: 29), nr_events: 1
task 10 ( migration/15: 33), nr_events: 1
task 11 ( migration/9: 21), nr_events: 1
task 12 ( sh: 6614), nr_events: 4
task 13 ( make: 6615), nr_events: 5
task 14 ( sh: 6616), nr_events: 4
task 15 ( make: 6617), nr_events: 7
task 16 ( migration/3: 9), nr_events: 1
task 17 ( migration/5: 13), nr_events: 1
task 18 ( migration/7: 17), nr_events: 1
task 19 ( migration/1: 5), nr_events: 1
task 20 ( sh: 6618), nr_events: 4
task 21 ( make: 6619), nr_events: 5
task 22 ( sh: 6620), nr_events: 4
task 23 ( make: 6621), nr_events: 10
task 24 ( sh: 6623), nr_events: 3
task 25 ( gcc: 6624), nr_events: 4
task 26 ( gcc: 6625), nr_events: 4
task 27 ( gcc: 6626), nr_events: 5
task 28 ( collect2: 6627), nr_events: 5
task 29 ( sh: 6622), nr_events: 1
task 30 ( make: 6628), nr_events: 7
task 31 ( sh: 6630), nr_events: 4
task 32 ( gcc: 6631), nr_events: 4
task 33 ( sh: 6629), nr_events: 1
task 34 ( gcc: 6632), nr_events: 4
task 35 ( gcc: 6633), nr_events: 4
task 36 ( collect2: 6634), nr_events: 4
task 37 ( make: 6635), nr_events: 8
task 38 ( sh: 6637), nr_events: 4
task 39 ( sh: 6636), nr_events: 1
task 40 ( gcc: 6638), nr_events: 4
task 41 ( gcc: 6639), nr_events: 4
task 42 ( gcc: 6640), nr_events: 4
task 43 ( collect2: 6641), nr_events: 4
task 44 ( make: 6642), nr_events: 6
task 45 ( sh: 6643), nr_events: 5
task 46 ( sh: 6644), nr_events: 3
task 47 ( sh: 6645), nr_events: 4
task 48 ( make: 6646), nr_events: 6
task 49 ( sh: 6647), nr_events: 3
task 50 ( make: 6648), nr_events: 5
task 51 ( sh: 6649), nr_events: 5
task 52 ( sh: 6650), nr_events: 6
task 53 ( make: 6651), nr_events: 4
task 54 ( make: 6652), nr_events: 5
task 55 ( make: 6653), nr_events: 4
task 56 ( make: 6654), nr_events: 4
task 57 ( make: 6655), nr_events: 5
task 58 ( sh: 6656), nr_events: 4
task 59 ( gcc: 6657), nr_events: 9
task 60 ( ksoftirqd/3: 10), nr_events: 1
task 61 ( gcc: 6658), nr_events: 4
task 62 ( make: 6659), nr_events: 5
task 63 ( sh: 6660), nr_events: 3
task 64 ( gcc: 6661), nr_events: 5
task 65 ( collect2: 6662), nr_events: 4
------------------------------------------------------------
#1 : 256.745, ravg: 256.74, cpu: 0.00 / 0.00
#2 : 439.372, ravg: 275.01, cpu: 0.00 / 0.00
#3 : 411.971, ravg: 288.70, cpu: 0.00 / 0.00
#4 : 385.500, ravg: 298.38, cpu: 0.00 / 0.00
#5 : 366.526, ravg: 305.20, cpu: 0.00 / 0.00
#6 : 381.281, ravg: 312.81, cpu: 0.00 / 0.00
#7 : 410.756, ravg: 322.60, cpu: 0.00 / 0.00
#8 : 368.009, ravg: 327.14, cpu: 0.00 / 0.00
#9 : 408.098, ravg: 335.24, cpu: 0.00 / 0.00
#10 : 368.582, ravg: 338.57, cpu: 0.00 / 0.00
I.e. we successfully analyzed the trace, replayed it
via real threads and measured the replayed workload's
scheduling properties.
This is how it looked like in 'top' output:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7164 mingo 20 0 1434m 8080 888 R 57.0 0.1 0:02.04 :perf
7165 mingo 20 0 1434m 8080 888 R 41.8 0.1 0:01.52 :perf
7228 mingo 20 0 1434m 8080 888 R 39.8 0.1 0:01.44 :gcc
7225 mingo 20 0 1434m 8080 888 R 33.8 0.1 0:01.26 :gcc
7202 mingo 20 0 1434m 8080 888 R 31.2 0.1 0:01.16 :sh
7222 mingo 20 0 1434m 8080 888 R 25.2 0.1 0:00.96 :sh
7211 mingo 20 0 1434m 8080 888 R 21.9 0.1 0:00.82 :sh
7213 mingo 20 0 1434m 8080 888 D 19.2 0.1 0:00.74 :sh
7194 mingo 20 0 1434m 8080 888 D 18.6 0.1 0:00.72 :make
There's still various kinks in it - more patches to come.
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>
2009-09-11 18:12:54 +08:00
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
if (verbose)
|
|
|
|
printf("sched_exit event %p\n", event);
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
process_sched_migrate_task_event(struct perf_tool *tool __used,
|
2012-04-06 06:47:56 +08:00
|
|
|
struct event_format *event,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine,
|
2012-08-07 22:33:42 +08:00
|
|
|
struct thread *thread __used)
|
2009-10-10 20:46:04 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
void *data = sample->raw_data;
|
2009-10-10 20:46:04 +08:00
|
|
|
struct trace_migrate_task_event migrate_task_event;
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = 0;
|
2009-10-10 20:46:04 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_COMMON_FIELDS(migrate_task_event, event, data);
|
2009-10-10 20:46:04 +08:00
|
|
|
|
2009-12-07 13:04:04 +08:00
|
|
|
FILL_ARRAY(migrate_task_event, comm, event, data);
|
|
|
|
FILL_FIELD(migrate_task_event, pid, event, data);
|
|
|
|
FILL_FIELD(migrate_task_event, prio, event, data);
|
|
|
|
FILL_FIELD(migrate_task_event, cpu, event, data);
|
2009-10-10 20:46:04 +08:00
|
|
|
|
|
|
|
if (trace_handler->migrate_task_event)
|
2012-09-09 09:53:06 +08:00
|
|
|
err = trace_handler->migrate_task_event(&migrate_task_event, machine, sample);
|
|
|
|
|
|
|
|
return err;
|
2009-10-10 20:46:04 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
typedef int (*tracepoint_handler)(struct perf_tool *tool,
|
|
|
|
struct event_format *tp_format,
|
|
|
|
struct perf_sample *sample,
|
|
|
|
struct machine *machine,
|
|
|
|
struct thread *thread);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2012-08-07 20:58:03 +08:00
|
|
|
static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __used,
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
union perf_event *event __used,
|
|
|
|
struct perf_sample *sample,
|
|
|
|
struct perf_evsel *evsel,
|
|
|
|
struct machine *machine)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
struct thread *thread = machine__findnew_thread(machine, sample->pid);
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = 0;
|
2009-09-11 18:12:54 +08:00
|
|
|
|
|
|
|
if (thread == NULL) {
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
pr_debug("problem processing %s event, skipping it.\n",
|
2012-06-13 00:55:13 +08:00
|
|
|
perf_evsel__name(evsel));
|
2009-09-11 18:12:54 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
evsel->hists.stats.total_period += sample->period;
|
|
|
|
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
2009-10-17 14:43:17 +08:00
|
|
|
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
if (evsel->handler.func != NULL) {
|
|
|
|
tracepoint_handler f = evsel->handler.func;
|
2012-09-09 09:53:06 +08:00
|
|
|
err = f(tool, evsel->tp_format, sample, machine, thread);
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
}
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
return err;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2012-08-07 20:58:03 +08:00
|
|
|
static struct perf_tool perf_sched = {
|
|
|
|
.sample = perf_sched__process_tracepoint_sample,
|
|
|
|
.comm = perf_event__process_comm,
|
|
|
|
.lost = perf_event__process_lost,
|
|
|
|
.fork = perf_event__process_task,
|
|
|
|
.ordered_samples = true,
|
2009-10-07 18:47:31 +08:00
|
|
|
};
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int read_events(bool destroy, struct perf_session **psession)
|
2009-09-11 18:12:54 +08:00
|
|
|
{
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
const struct perf_evsel_str_handler handlers[] = {
|
|
|
|
{ "sched:sched_switch", process_sched_switch_event, },
|
|
|
|
{ "sched:sched_stat_runtime", process_sched_runtime_event, },
|
|
|
|
{ "sched:sched_wakeup", process_sched_wakeup_event, },
|
|
|
|
{ "sched:sched_wakeup_new", process_sched_wakeup_event, },
|
|
|
|
{ "sched:sched_process_fork", process_sched_fork_event, },
|
|
|
|
{ "sched:sched_process_exit", process_sched_exit_event, },
|
|
|
|
{ "sched:sched_migrate_task", process_sched_migrate_task_event, },
|
|
|
|
};
|
2012-06-28 00:08:42 +08:00
|
|
|
struct perf_session *session;
|
|
|
|
|
2012-08-07 20:58:03 +08:00
|
|
|
session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_sched);
|
2012-09-09 09:53:06 +08:00
|
|
|
if (session == NULL) {
|
|
|
|
pr_debug("No Memory for session\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2009-12-12 07:24:02 +08:00
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
if (perf_session__set_tracepoints_handlers(session, handlers))
|
|
|
|
goto out_delete;
|
perf tools: Save some loops using perf_evlist__id2evsel
Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.
To demonstrate the technique convert 'perf sched' to it:
# perf sched record sleep 5m
And then:
Performance counter stats for '/tmp/oldperf sched lat':
646.929438 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,901 page-faults # 0.032 M/sec
1,290,144,450 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,606,158,439 instructions # 1.24 insns per cycle
339,088,395 branches # 524.151 M/sec
4,550,735 branch-misses # 1.34% of all branches
0.647524759 seconds time elapsed
Versus:
Performance counter stats for 'perf sched lat':
473.564691 task-clock # 0.999 CPUs utilized
9 context-switches # 0.000 M/sec
0 CPU-migrations # 0.000 M/sec
20,903 page-faults # 0.044 M/sec
944,367,984 cycles # 1.994 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,442,385,571 instructions # 1.53 insns per cycle
308,383,106 branches # 651.195 M/sec
4,481,784 branch-misses # 1.45% of all branches
0.474215751 seconds time elapsed
[root@emilia ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2011-11-29 03:57:40 +08:00
|
|
|
|
2010-05-15 00:16:55 +08:00
|
|
|
if (perf_session__has_traces(session, "record -R")) {
|
2012-09-09 09:53:06 +08:00
|
|
|
int err = perf_session__process_events(session, &perf_sched);
|
|
|
|
if (err) {
|
|
|
|
pr_err("Failed to process events, error %d", err);
|
|
|
|
goto out_delete;
|
|
|
|
}
|
2011-08-09 05:03:34 +08:00
|
|
|
|
2010-05-15 00:16:55 +08:00
|
|
|
nr_events = session->hists.stats.nr_events[0];
|
|
|
|
nr_lost_events = session->hists.stats.total_lost;
|
|
|
|
nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
|
|
|
|
}
|
2009-12-28 07:37:02 +08:00
|
|
|
|
2011-08-09 05:03:34 +08:00
|
|
|
if (destroy)
|
|
|
|
perf_session__delete(session);
|
|
|
|
|
|
|
|
if (psession)
|
|
|
|
*psession = session;
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out_delete:
|
|
|
|
perf_session__delete(session);
|
|
|
|
return -1;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
static void print_bad_events(void)
|
|
|
|
{
|
|
|
|
if (nr_unordered_timestamps && nr_timestamps) {
|
|
|
|
printf(" INFO: %.3f%% unordered timestamps (%ld out of %ld)\n",
|
|
|
|
(double)nr_unordered_timestamps/(double)nr_timestamps*100.0,
|
|
|
|
nr_unordered_timestamps, nr_timestamps);
|
|
|
|
}
|
|
|
|
if (nr_lost_events && nr_events) {
|
|
|
|
printf(" INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n",
|
|
|
|
(double)nr_lost_events/(double)nr_events*100.0,
|
|
|
|
nr_lost_events, nr_events, nr_lost_chunks);
|
|
|
|
}
|
|
|
|
if (nr_state_machine_bugs && nr_timestamps) {
|
|
|
|
printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)",
|
|
|
|
(double)nr_state_machine_bugs/(double)nr_timestamps*100.0,
|
|
|
|
nr_state_machine_bugs, nr_timestamps);
|
|
|
|
if (nr_lost_events)
|
|
|
|
printf(" (due to lost events?)");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
if (nr_context_switch_bugs && nr_timestamps) {
|
|
|
|
printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)",
|
|
|
|
(double)nr_context_switch_bugs/(double)nr_timestamps*100.0,
|
|
|
|
nr_context_switch_bugs, nr_timestamps);
|
|
|
|
if (nr_lost_events)
|
|
|
|
printf(" (due to lost events?)");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int __cmd_lat(void)
|
2009-09-16 23:40:48 +08:00
|
|
|
{
|
|
|
|
struct rb_node *next;
|
2011-08-09 05:03:34 +08:00
|
|
|
struct perf_session *session;
|
2009-09-16 23:40:48 +08:00
|
|
|
|
|
|
|
setup_pager();
|
2012-09-09 09:53:06 +08:00
|
|
|
if (read_events(false, &session))
|
|
|
|
return -1;
|
2009-09-16 23:40:48 +08:00
|
|
|
sort_lat();
|
|
|
|
|
2009-12-10 04:40:08 +08:00
|
|
|
printf("\n ---------------------------------------------------------------------------------------------------------------\n");
|
|
|
|
printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n");
|
|
|
|
printf(" ---------------------------------------------------------------------------------------------------------------\n");
|
2009-09-16 23:40:48 +08:00
|
|
|
|
|
|
|
next = rb_first(&sorted_atom_root);
|
|
|
|
|
|
|
|
while (next) {
|
|
|
|
struct work_atoms *work_list;
|
|
|
|
|
|
|
|
work_list = rb_entry(next, struct work_atoms, node);
|
|
|
|
output_lat_thread(work_list);
|
|
|
|
next = rb_next(next);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" -----------------------------------------------------------------------------------------\n");
|
2011-01-23 06:37:02 +08:00
|
|
|
printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
|
2009-09-16 23:40:48 +08:00
|
|
|
(double)all_runtime/1e6, all_count);
|
|
|
|
|
|
|
|
printf(" ---------------------------------------------------\n");
|
|
|
|
|
|
|
|
print_bad_events();
|
|
|
|
printf("\n");
|
|
|
|
|
2011-08-09 05:03:34 +08:00
|
|
|
perf_session__delete(session);
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-16 23:40:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct trace_sched_handler map_ops = {
|
|
|
|
.wakeup_event = NULL,
|
|
|
|
.switch_event = map_switch_event,
|
|
|
|
.runtime_event = NULL,
|
|
|
|
.fork_event = NULL,
|
|
|
|
};
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int __cmd_map(void)
|
2009-09-16 23:40:48 +08:00
|
|
|
{
|
2009-09-18 00:24:55 +08:00
|
|
|
max_cpu = sysconf(_SC_NPROCESSORS_CONF);
|
|
|
|
|
2009-09-16 23:40:48 +08:00
|
|
|
setup_pager();
|
2012-09-09 09:53:06 +08:00
|
|
|
if (read_events(true, NULL))
|
|
|
|
return -1;
|
2009-09-16 23:40:48 +08:00
|
|
|
print_bad_events();
|
2012-09-09 09:53:06 +08:00
|
|
|
return 0;
|
2009-09-16 23:40:48 +08:00
|
|
|
}
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
static int __cmd_replay(void)
|
2009-09-16 23:40:48 +08:00
|
|
|
{
|
|
|
|
unsigned long i;
|
|
|
|
|
|
|
|
calibrate_run_measurement_overhead();
|
|
|
|
calibrate_sleep_measurement_overhead();
|
|
|
|
|
|
|
|
test_calibrations();
|
|
|
|
|
2012-09-09 09:53:06 +08:00
|
|
|
if (read_events(true, NULL))
|
|
|
|
return -1;
|
2009-09-16 23:40:48 +08:00
|
|
|
|
|
|
|
printf("nr_run_events: %ld\n", nr_run_events);
|
|
|
|
printf("nr_sleep_events: %ld\n", nr_sleep_events);
|
|
|
|
printf("nr_wakeup_events: %ld\n", nr_wakeup_events);
|
|
|
|
|
|
|
|
if (targetless_wakeups)
|
|
|
|
printf("target-less wakeups: %ld\n", targetless_wakeups);
|
|
|
|
if (multitarget_wakeups)
|
|
|
|
printf("multi-target wakeups: %ld\n", multitarget_wakeups);
|
|
|
|
if (nr_run_events_optimized)
|
|
|
|
printf("run atoms optimized: %ld\n",
|
|
|
|
nr_run_events_optimized);
|
|
|
|
|
|
|
|
print_task_traces();
|
|
|
|
add_cross_task_wakeups();
|
|
|
|
|
|
|
|
create_tasks();
|
|
|
|
printf("------------------------------------------------------------\n");
|
|
|
|
for (i = 0; i < replay_repeat; i++)
|
|
|
|
run_one_test();
|
2012-09-09 09:53:06 +08:00
|
|
|
|
|
|
|
return 0;
|
2009-09-16 23:40:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-12 16:08:34 +08:00
|
|
|
static const char * const sched_usage[] = {
|
2011-08-09 20:46:51 +08:00
|
|
|
"perf sched [<options>] {record|latency|map|replay|script}",
|
2009-09-11 18:12:54 +08:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
static const struct option sched_options[] = {
|
2009-09-18 14:22:24 +08:00
|
|
|
OPT_STRING('i', "input", &input_name, "file",
|
|
|
|
"input file name"),
|
2010-04-13 16:37:33 +08:00
|
|
|
OPT_INCR('v', "verbose", &verbose,
|
2009-09-11 18:12:54 +08:00
|
|
|
"be more verbose (show symbol address, etc)"),
|
2009-09-11 18:12:54 +08:00
|
|
|
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
|
|
|
"dump raw trace in ASCII"),
|
2009-09-11 18:12:54 +08:00
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char * const latency_usage[] = {
|
|
|
|
"perf sched latency [<options>]",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct option latency_options[] = {
|
2009-09-13 09:36:29 +08:00
|
|
|
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
|
|
|
|
"sort by key(s): runtime, switch, avg, max"),
|
2010-04-13 16:37:33 +08:00
|
|
|
OPT_INCR('v', "verbose", &verbose,
|
2009-09-11 18:12:54 +08:00
|
|
|
"be more verbose (show symbol address, etc)"),
|
2009-10-10 20:46:04 +08:00
|
|
|
OPT_INTEGER('C', "CPU", &profile_cpu,
|
|
|
|
"CPU to profile on"),
|
2009-09-11 18:12:54 +08:00
|
|
|
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
|
|
|
"dump raw trace in ASCII"),
|
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char * const replay_usage[] = {
|
|
|
|
"perf sched replay [<options>]",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct option replay_options[] = {
|
2010-05-18 02:39:16 +08:00
|
|
|
OPT_UINTEGER('r', "repeat", &replay_repeat,
|
|
|
|
"repeat the workload replay N times (-1: infinite)"),
|
2010-04-13 16:37:33 +08:00
|
|
|
OPT_INCR('v', "verbose", &verbose,
|
2009-09-11 18:12:54 +08:00
|
|
|
"be more verbose (show symbol address, etc)"),
|
|
|
|
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
|
|
|
"dump raw trace in ASCII"),
|
2009-09-11 18:12:54 +08:00
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
2009-09-13 09:36:29 +08:00
|
|
|
static void setup_sorting(void)
|
|
|
|
{
|
|
|
|
char *tmp, *tok, *str = strdup(sort_order);
|
|
|
|
|
|
|
|
for (tok = strtok_r(str, ", ", &tmp);
|
|
|
|
tok; tok = strtok_r(NULL, ", ", &tmp)) {
|
|
|
|
if (sort_dimension__add(tok, &sort_list) < 0) {
|
|
|
|
error("Unknown --sort key: `%s'", tok);
|
2009-09-11 18:12:54 +08:00
|
|
|
usage_with_options(latency_usage, latency_options);
|
2009-09-13 09:36:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(str);
|
|
|
|
|
2009-10-06 04:17:29 +08:00
|
|
|
sort_dimension__add("pid", &cmp_pid);
|
2009-09-13 09:36:29 +08:00
|
|
|
}
|
|
|
|
|
2009-09-13 15:44:29 +08:00
|
|
|
static const char *record_args[] = {
|
|
|
|
"record",
|
|
|
|
"-a",
|
|
|
|
"-R",
|
2009-09-14 00:15:54 +08:00
|
|
|
"-f",
|
2009-09-16 19:45:00 +08:00
|
|
|
"-m", "1024",
|
2009-09-13 15:44:29 +08:00
|
|
|
"-c", "1",
|
2011-01-12 17:29:05 +08:00
|
|
|
"-e", "sched:sched_switch",
|
|
|
|
"-e", "sched:sched_stat_wait",
|
|
|
|
"-e", "sched:sched_stat_sleep",
|
|
|
|
"-e", "sched:sched_stat_iowait",
|
|
|
|
"-e", "sched:sched_stat_runtime",
|
|
|
|
"-e", "sched:sched_process_exit",
|
|
|
|
"-e", "sched:sched_process_fork",
|
|
|
|
"-e", "sched:sched_wakeup",
|
|
|
|
"-e", "sched:sched_migrate_task",
|
2009-09-13 15:44:29 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int __cmd_record(int argc, const char **argv)
|
|
|
|
{
|
|
|
|
unsigned int rec_argc, i, j;
|
|
|
|
const char **rec_argv;
|
|
|
|
|
|
|
|
rec_argc = ARRAY_SIZE(record_args) + argc - 1;
|
|
|
|
rec_argv = calloc(rec_argc + 1, sizeof(char *));
|
|
|
|
|
2011-01-10 20:48:47 +08:00
|
|
|
if (rec_argv == NULL)
|
2010-11-13 10:35:06 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2009-09-13 15:44:29 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(record_args); i++)
|
|
|
|
rec_argv[i] = strdup(record_args[i]);
|
|
|
|
|
|
|
|
for (j = 1; j < (unsigned int)argc; j++, i++)
|
|
|
|
rec_argv[i] = argv[j];
|
|
|
|
|
|
|
|
BUG_ON(i != rec_argc);
|
|
|
|
|
|
|
|
return cmd_record(i, rec_argv, NULL);
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
int cmd_sched(int argc, const char **argv, const char *prefix __used)
|
|
|
|
{
|
2009-09-11 18:12:54 +08:00
|
|
|
argc = parse_options(argc, argv, sched_options, sched_usage,
|
|
|
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
|
|
|
if (!argc)
|
|
|
|
usage_with_options(sched_usage, sched_options);
|
2009-09-11 18:12:54 +08:00
|
|
|
|
2009-12-07 12:04:49 +08:00
|
|
|
/*
|
2010-11-17 01:45:39 +08:00
|
|
|
* Aliased to 'perf script' for now:
|
2009-12-07 12:04:49 +08:00
|
|
|
*/
|
2010-11-17 01:45:39 +08:00
|
|
|
if (!strcmp(argv[0], "script"))
|
|
|
|
return cmd_script(argc, argv, prefix);
|
2009-12-07 12:04:49 +08:00
|
|
|
|
2009-12-16 06:04:39 +08:00
|
|
|
symbol__init();
|
2009-09-13 15:44:29 +08:00
|
|
|
if (!strncmp(argv[0], "rec", 3)) {
|
|
|
|
return __cmd_record(argc, argv);
|
|
|
|
} else if (!strncmp(argv[0], "lat", 3)) {
|
2009-09-12 14:06:14 +08:00
|
|
|
trace_handler = &lat_ops;
|
2009-09-11 18:12:54 +08:00
|
|
|
if (argc > 1) {
|
|
|
|
argc = parse_options(argc, argv, latency_options, latency_usage, 0);
|
|
|
|
if (argc)
|
|
|
|
usage_with_options(latency_usage, latency_options);
|
|
|
|
}
|
2009-09-11 18:12:54 +08:00
|
|
|
setup_sorting();
|
2012-09-09 09:53:06 +08:00
|
|
|
return __cmd_lat();
|
2009-09-16 23:40:48 +08:00
|
|
|
} else if (!strcmp(argv[0], "map")) {
|
|
|
|
trace_handler = &map_ops;
|
|
|
|
setup_sorting();
|
2012-09-09 09:53:06 +08:00
|
|
|
return __cmd_map();
|
2009-09-11 18:12:54 +08:00
|
|
|
} else if (!strncmp(argv[0], "rep", 3)) {
|
|
|
|
trace_handler = &replay_ops;
|
|
|
|
if (argc) {
|
|
|
|
argc = parse_options(argc, argv, replay_options, replay_usage, 0);
|
|
|
|
if (argc)
|
|
|
|
usage_with_options(replay_usage, replay_options);
|
|
|
|
}
|
2012-09-09 09:53:06 +08:00
|
|
|
return __cmd_replay();
|
2009-09-11 18:12:54 +08:00
|
|
|
} else {
|
|
|
|
usage_with_options(sched_usage, sched_options);
|
|
|
|
}
|
|
|
|
|
2009-09-11 18:12:54 +08:00
|
|
|
return 0;
|
2009-09-11 18:12:54 +08:00
|
|
|
}
|