Patches contributed by Eötvös Lorand University
commit 136107a76fe5f62906162f730834477b71cf131e
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 17:56:21 2009 +0200
perf_counter tools: Remove -march=native
Turns out that neither PowerPC nor older x86 compilers know this switch
...
and since it does not make a measurable difference, just omit it.
Reported-by: Paul Mackerras <paulus@samba.org>
Reported-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index c9ec4585f4d6..5b99f04df812 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -159,7 +159,7 @@ uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
# CFLAGS and LDFLAGS are for the users to override from the command line.
-CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6 -march=native
+CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6
LDFLAGS = -lpthread -lrt -lelf
ALL_CFLAGS = $(CFLAGS)
ALL_LDFLAGS = $(LDFLAGS)
commit 918143e8b7d6153d7a83a3f854323407939f4a7e
Merge: 64edbc562034 563af16c30ed
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 16:50:29 2009 +0200
Merge branch 'tip/tracing/ftrace-4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
commit 2debbc836696f2a815d02630230584a1754a5022
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 14:29:10 2009 +0200
perf_counter tools: Clarify events/samples naming
A number of places said 'events' while they should say 'samples'.
Acked-by: 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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index e2301f39e551..d4ad3057a711 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -65,7 +65,7 @@ static unsigned int mmap_read_head(struct mmap_data *md)
return head;
}
-static long events;
+static long samples;
static struct timeval last_read, this_read;
static __u64 bytes_written;
@@ -83,7 +83,7 @@ static void mmap_read(struct mmap_data *md)
/*
* If we're further behind than half the buffer, there's a chance
- * the writer will bite our tail and screw up the events under us.
+ * the writer will bite our tail and mess up the samples under us.
*
* If we somehow ended up ahead of the head, we got messed up.
*
@@ -109,7 +109,7 @@ static void mmap_read(struct mmap_data *md)
last_read = this_read;
if (old != head)
- events++;
+ samples++;
size = head - old;
@@ -257,7 +257,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
exit(EXIT_FAILURE);
}
-static void pid_synthesize_mmap_events(pid_t pid)
+static void pid_synthesize_mmap_samples(pid_t pid)
{
char filename[PATH_MAX];
FILE *fp;
@@ -315,7 +315,7 @@ static void pid_synthesize_mmap_events(pid_t pid)
fclose(fp);
}
-static void synthesize_events(void)
+static void synthesize_samples(void)
{
DIR *proc;
struct dirent dirent, *next;
@@ -331,7 +331,7 @@ static void synthesize_events(void)
continue;
pid_synthesize_comm_event(pid, 1);
- pid_synthesize_mmap_events(pid);
+ pid_synthesize_mmap_samples(pid);
}
closedir(proc);
@@ -396,7 +396,7 @@ static void open_counters(int cpu, pid_t pid)
if (pid > 0) {
pid_synthesize_comm_event(pid, 0);
- pid_synthesize_mmap_events(pid);
+ pid_synthesize_mmap_samples(pid);
}
group_fd = -1;
@@ -469,17 +469,17 @@ static int __cmd_record(int argc, const char **argv)
}
if (system_wide)
- synthesize_events();
+ synthesize_samples();
while (!done) {
- int hits = events;
+ int hits = samples;
for (i = 0; i < nr_cpu; i++) {
for (counter = 0; counter < nr_counters; counter++)
mmap_read(&mmap_array[i][counter]);
}
- if (hits == events)
+ if (hits == samples)
ret = poll(event_array, nr_poll, 100);
}
@@ -487,7 +487,7 @@ static int __cmd_record(int argc, const char **argv)
* Approximate RIP event size: 24 bytes.
*/
fprintf(stderr,
- "[ perf record: Captured and wrote %.3f MB %s (~%lld events) ]\n",
+ "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n",
(double)bytes_written / 1024.0 / 1024.0,
output_name,
bytes_written / 24);
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index ca303fd74a71..5af105c280b5 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -857,7 +857,7 @@ static size_t output__fprintf(FILE *fp, uint64_t total_samples)
fprintf(fp, "\n");
fprintf(fp, "#\n");
- fprintf(fp, "# (%Ld profiler events)\n", (__u64)total_samples);
+ fprintf(fp, "# (%Ld samples)\n", (__u64)total_samples);
fprintf(fp, "#\n");
fprintf(fp, "# Overhead");
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 2fee5951b231..ff7e13c4647c 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -137,8 +137,8 @@ static double sym_weight(const struct sym_entry *sym)
return weight;
}
-static long events;
-static long userspace_events;
+static long samples;
+static long userspace_samples;
static const char CONSOLE_CLEAR[] = "[H[2J";
static void __list_insert_active_sym(struct sym_entry *syme)
@@ -177,14 +177,14 @@ static void print_sym_table(void)
{
int printed = 0, j;
int counter;
- float events_per_sec = events/delay_secs;
- float kevents_per_sec = (events-userspace_events)/delay_secs;
- float sum_kevents = 0.0;
+ float samples_per_sec = samples/delay_secs;
+ float ksamples_per_sec = (samples-userspace_samples)/delay_secs;
+ float sum_ksamples = 0.0;
struct sym_entry *syme, *n;
struct rb_root tmp = RB_ROOT;
struct rb_node *nd;
- events = userspace_events = 0;
+ samples = userspace_samples = 0;
/* Sort the active symbols */
pthread_mutex_lock(&active_symbols_lock);
@@ -196,7 +196,7 @@ static void print_sym_table(void)
if (syme->snap_count != 0) {
syme->weight = sym_weight(syme);
rb_insert_active_sym(&tmp, syme);
- sum_kevents += syme->snap_count;
+ sum_ksamples += syme->snap_count;
for (j = 0; j < nr_counters; j++)
syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
@@ -209,8 +209,8 @@ static void print_sym_table(void)
printf(
"------------------------------------------------------------------------------\n");
printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
- events_per_sec,
- 100.0 - (100.0*((events_per_sec-kevents_per_sec)/events_per_sec)));
+ samples_per_sec,
+ 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
if (nr_counters == 1) {
printf("%d", event_count[0]);
@@ -246,12 +246,12 @@ static void print_sym_table(void)
printf("------------------------------------------------------------------------------\n\n");
if (nr_counters == 1)
- printf(" events pcnt");
+ printf(" samples pcnt");
else
- printf(" weight events pcnt");
+ printf(" weight samples pcnt");
printf(" RIP kernel function\n"
- " ______ ______ _____ ________________ _______________\n\n"
+ " ______ _______ _____ ________________ _______________\n\n"
);
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
@@ -263,8 +263,8 @@ static void print_sym_table(void)
if (++printed > print_entries || syme->snap_count < count_filter)
continue;
- pcnt = 100.0 - (100.0 * ((sum_kevents - syme->snap_count) /
- sum_kevents));
+ pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
+ sum_ksamples));
/*
* We color high-overhead entries in red, low-overhead
@@ -276,9 +276,9 @@ static void print_sym_table(void)
color = PERF_COLOR_GREEN;
if (nr_counters == 1)
- printf("%19.2f - ", syme->weight);
+ printf("%20.2f - ", syme->weight);
else
- printf("%8.1f %10ld - ", syme->weight, syme->snap_count);
+ printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
color_fprintf(stdout, color, "%4.1f%%", pcnt);
printf(" - %016llx : %s\n", sym->start, sym->name);
@@ -318,7 +318,7 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
return 1;
syme = dso__sym_priv(self, sym);
- /* Tag events to be skipped. */
+ /* Tag samples to be skipped. */
if (!strcmp("default_idle", name) ||
!strcmp("cpu_idle", name) ||
!strcmp("enter_idle", name) ||
@@ -405,15 +405,15 @@ static void record_ip(uint64_t ip, int counter)
}
}
- events--;
+ samples--;
}
static void process_event(uint64_t ip, int counter)
{
- events++;
+ samples++;
if (ip < min_ip || ip > max_ip) {
- userspace_events++;
+ userspace_samples++;
return;
}
@@ -451,7 +451,7 @@ static void mmap_read(struct mmap_data *md)
/*
* If we're further behind than half the buffer, there's a chance
- * the writer will bite our tail and screw up the events under us.
+ * the writer will bite our tail and mess up the samples under us.
*
* If we somehow ended up ahead of the head, we got messed up.
*
@@ -608,14 +608,14 @@ static int __cmd_top(void)
}
while (1) {
- int hits = events;
+ int hits = samples;
for (i = 0; i < nr_cpus; i++) {
for (counter = 0; counter < nr_counters; counter++)
mmap_read(&mmap_array[i][counter]);
}
- if (hits == events)
+ if (hits == samples)
ret = poll(event_array, nr_poll, 100);
}
commit 8edd4286f99f78fe07fe9196e69d5643da86cada
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 14:13:18 2009 +0200
perf report: Display user/kernel differentiator
Before:
25.96% copy_user_generic_string
15.23% two_op
15.19% one_op
6.92% enough_duration
1.23% alloc_pages_current
1.14% acpi_os_read_port
1.08% _spin_lock
After:
25.96% [k] copy_user_generic_string
15.23% [.] two_op
15.19% [.] one_op
6.92% [.] enough_duration
1.23% [k] alloc_pages_current
1.14% [k] acpi_os_read_port
1.08% [k] _spin_lock
The '[k]' differentiator is a quick clue that it's a kernel symbol,
without having to bring in the full dso column.
Acked-by: 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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 9783d1e493c4..ca303fd74a71 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -504,7 +504,7 @@ sort__comm_print(FILE *fp, struct hist_entry *self)
}
static struct sort_entry sort_comm = {
- .header = " Command",
+ .header = " Command",
.cmp = sort__comm_cmp,
.collapse = sort__comm_collapse,
.print = sort__comm_print,
@@ -569,10 +569,12 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
if (verbose)
ret += fprintf(fp, "%#018llx ", (__u64)self->ip);
- if (self->sym)
- ret += fprintf(fp, "%s", self->sym->name);
- else
+ if (self->sym) {
+ ret += fprintf(fp, "[%c] %s",
+ self->dso == kernel_dso ? 'k' : '.', self->sym->name);
+ } else {
ret += fprintf(fp, "%#016llx", (__u64)self->ip);
+ }
return ret;
}
@@ -586,9 +588,9 @@ static struct sort_entry sort_sym = {
static int sort__need_collapse = 0;
struct sort_dimension {
- char *name;
- struct sort_entry *entry;
- int taken;
+ char *name;
+ struct sort_entry *entry;
+ int taken;
};
static struct sort_dimension sort_dimensions[] = {
commit cf1f45744c6fa3501e0a6f0ddc418f0ef27e725b
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 13:27:02 2009 +0200
perf record, top: Implement --freq
Support frequency-based profiling and make it the default.
(Also add a Hz printout in perf top.)
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index 7f2d7ce94075..e2301f39e551 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -27,6 +27,7 @@ static int fd[MAX_NR_CPUS][MAX_COUNTERS];
static int nr_cpus = 0;
static unsigned int page_size;
static unsigned int mmap_pages = 128;
+static int freq = 0;
static int output;
static const char *output_name = "perf.data";
static int group = 0;
@@ -347,9 +348,10 @@ static void create_counter(int counter, int cpu, pid_t pid)
attr.config = event_id[counter];
attr.sample_period = event_count[counter];
attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+ attr.freq = freq;
attr.mmap = track;
attr.comm = track;
- attr.inherit = (cpu < 0) && inherit;
+ attr.inherit = (cpu < 0) && inherit;
track = 0; /* only the first counter needs these */
@@ -520,6 +522,8 @@ static const struct option options[] = {
"output file name"),
OPT_BOOLEAN('i', "inherit", &inherit,
"child tasks inherit counters"),
+ OPT_INTEGER('F', "freq", &freq,
+ "profile at this frequency"),
OPT_INTEGER('m', "mmap-pages", &mmap_pages,
"number of mmap data pages"),
OPT_END()
@@ -540,6 +544,10 @@ int cmd_record(int argc, const char **argv, const char *prefix)
event_id[0] = 0;
}
+ if (freq) {
+ default_interval = freq;
+ freq = 1;
+ }
for (counter = 0; counter < nr_counters; counter++) {
if (event_count[counter])
continue;
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 28cbde4b6e83..2fee5951b231 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -74,8 +74,8 @@ static int nr_cpus = 0;
static unsigned int realtime_prio = 0;
static int group = 0;
static unsigned int page_size;
-static unsigned int mmap_pages = 16;
-static int freq = 0;
+static unsigned int mmap_pages = 16;
+static int freq = 0;
static char *sym_filter;
static unsigned long filter_start;
@@ -212,8 +212,13 @@ static void print_sym_table(void)
events_per_sec,
100.0 - (100.0*((events_per_sec-kevents_per_sec)/events_per_sec)));
- if (nr_counters == 1)
- printf("%d ", event_count[0]);
+ if (nr_counters == 1) {
+ printf("%d", event_count[0]);
+ if (freq)
+ printf("Hz ");
+ else
+ printf(" ");
+ }
for (counter = 0; counter < nr_counters; counter++) {
if (counter)
commit f250c030a87273f8838a2302bee7c2b4d03e9151
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri Jun 5 13:18:41 2009 +0200
perf record: Split out counter creation into a helper function
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index bf59df5bddf3..7f2d7ce94075 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -336,65 +336,71 @@ static void synthesize_events(void)
closedir(proc);
}
-static void open_counters(int cpu, pid_t pid)
+static int group_fd;
+
+static void create_counter(int counter, int cpu, pid_t pid)
{
struct perf_counter_attr attr;
- int counter, group_fd;
int track = 1;
- if (pid > 0) {
- pid_synthesize_comm_event(pid, 0);
- pid_synthesize_mmap_events(pid);
- }
+ memset(&attr, 0, sizeof(attr));
+ attr.config = event_id[counter];
+ attr.sample_period = event_count[counter];
+ attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+ attr.mmap = track;
+ attr.comm = track;
+ attr.inherit = (cpu < 0) && inherit;
- group_fd = -1;
- for (counter = 0; counter < nr_counters; counter++) {
+ track = 0; /* only the first counter needs these */
- memset(&attr, 0, sizeof(attr));
- attr.config = event_id[counter];
- attr.sample_period = event_count[counter];
- attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
- attr.mmap = track;
- attr.comm = track;
- attr.inherit = (cpu < 0) && inherit;
+ fd[nr_cpu][counter] = sys_perf_counter_open(&attr, pid, cpu, group_fd, 0);
- track = 0; // only the first counter needs these
+ if (fd[nr_cpu][counter] < 0) {
+ int err = errno;
- fd[nr_cpu][counter] =
- sys_perf_counter_open(&attr, pid, cpu, group_fd, 0);
+ error("syscall returned with %d (%s)\n",
+ fd[nr_cpu][counter], strerror(err));
+ if (err == EPERM)
+ printf("Are you root?\n");
+ exit(-1);
+ }
+ assert(fd[nr_cpu][counter] >= 0);
+ fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
- if (fd[nr_cpu][counter] < 0) {
- int err = errno;
+ /*
+ * First counter acts as the group leader:
+ */
+ if (group && group_fd == -1)
+ group_fd = fd[nr_cpu][counter];
+
+ event_array[nr_poll].fd = fd[nr_cpu][counter];
+ event_array[nr_poll].events = POLLIN;
+ nr_poll++;
+
+ mmap_array[nr_cpu][counter].counter = counter;
+ mmap_array[nr_cpu][counter].prev = 0;
+ mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
+ mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
+ PROT_READ, MAP_SHARED, fd[nr_cpu][counter], 0);
+ if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
+ error("failed to mmap with %d (%s)\n", errno, strerror(errno));
+ exit(-1);
+ }
+}
- error("syscall returned with %d (%s)\n",
- fd[nr_cpu][counter], strerror(err));
- if (err == EPERM)
- printf("Are you root?\n");
- exit(-1);
- }
- assert(fd[nr_cpu][counter] >= 0);
- fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
+static void open_counters(int cpu, pid_t pid)
+{
+ int counter;
- /*
- * First counter acts as the group leader:
- */
- if (group && group_fd == -1)
- group_fd = fd[nr_cpu][counter];
-
- event_array[nr_poll].fd = fd[nr_cpu][counter];
- event_array[nr_poll].events = POLLIN;
- nr_poll++;
-
- mmap_array[nr_cpu][counter].counter = counter;
- mmap_array[nr_cpu][counter].prev = 0;
- mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
- mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
- PROT_READ, MAP_SHARED, fd[nr_cpu][counter], 0);
- if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
- error("failed to mmap with %d (%s)\n", errno, strerror(errno));
- exit(-1);
- }
+ if (pid > 0) {
+ pid_synthesize_comm_event(pid, 0);
+ pid_synthesize_mmap_events(pid);
}
+
+ group_fd = -1;
+ for (counter = 0; counter < nr_counters; counter++)
+ create_counter(counter, cpu, pid);
+
nr_cpu++;
}
commit 20c84e959ec11b1803d2b2832eef703d5fbe7f7b
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 16:33:00 2009 +0200
perf stat: Update help text
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Documentation/perf-stat.txt b/Documentation/perf_counter/Documentation/perf-stat.txt
index a67d0e3b7d0d..a340e7be83dd 100644
--- a/Documentation/perf_counter/Documentation/perf-stat.txt
+++ b/Documentation/perf_counter/Documentation/perf-stat.txt
@@ -22,6 +22,7 @@ OPTIONS
<command>...::
Any command you can specify in a shell.
+
-e::
--event=::
0:0: cpu-cycles
@@ -45,6 +46,13 @@ OPTIONS
1:4: migrations
rNNN: raw PMU events (eventsel+umask)
+-i::
+--inherit::
+ child tasks inherit counters
+-p::
+--pid=<pid>::
+ stat events on existing pid
+
-a::
system-wide collection
@@ -54,20 +62,20 @@ OPTIONS
EXAMPLES
--------
-$ perf stat sleep 1
+$ perf stat -- make -j
- Performance counter stats for 'sleep':
+ Performance counter stats for 'make -j':
- 0.678356 task clock ticks (msecs)
- 7 context switches (events)
- 4 CPU migrations (events)
- 232 pagefaults (events)
- 1810403 CPU cycles (events)
- 946759 instructions (events)
- 18952 cache references (events)
- 4885 cache misses (events)
+ 8117.370256 task clock ticks # 11.281 CPU utilization factor
+ 678 context switches # 0.000 M/sec
+ 133 CPU migrations # 0.000 M/sec
+ 235724 pagefaults # 0.029 M/sec
+ 24821162526 CPU cycles # 3057.784 M/sec
+ 18687303457 instructions # 2302.138 M/sec
+ 172158895 cache references # 21.209 M/sec
+ 27075259 cache misses # 3.335 M/sec
- Wall-clock time elapsed: 1001.252894 msecs
+ Wall-clock time elapsed: 719.554352 msecs
SEE ALSO
--------
commit edc52deac624e4641211a325c23da2a73b01a85d
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 16:24:37 2009 +0200
perf report: Bail out if there are unrecognized options/arguments
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 7beedc6effa4..389ae2569f49 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -1094,10 +1094,16 @@ int cmd_report(int argc, const char **argv, const char *prefix)
page_size = getpagesize();
- parse_options(argc, argv, options, report_usage, 0);
+ argc = parse_options(argc, argv, options, report_usage, 0);
setup_sorting();
+ /*
+ * Any (unrecognized) arguments left?
+ */
+ if (argc)
+ usage_with_options(report_usage, options);
+
setup_pager();
return __cmd_report();
commit 13d0ab5ec29852a6925f612830fa9e822669ece6
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 15:40:25 2009 +0200
perf_counter tools: Dont output in color on !tty
Dont emit ASCII color characters if the terminal is not a tty,
such as when perf report gets redirected into a file.
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/util/color.c b/Documentation/perf_counter/util/color.c
index a77975d66774..9a8c20ccc53e 100644
--- a/Documentation/perf_counter/util/color.c
+++ b/Documentation/perf_counter/util/color.c
@@ -1,7 +1,7 @@
#include "cache.h"
#include "color.h"
-int perf_use_color_default = 0;
+int perf_use_color_default = -1;
static int parse_color(const char *name, int len)
{
@@ -169,10 +169,20 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
{
int r = 0;
- if (*color)
+ /*
+ * Auto-detect:
+ */
+ if (perf_use_color_default < 0) {
+ if (isatty(1) || pager_in_use())
+ perf_use_color_default = 1;
+ else
+ perf_use_color_default = 0;
+ }
+
+ if (perf_use_color_default && *color)
r += fprintf(fp, "%s", color);
r += vfprintf(fp, fmt, args);
- if (*color)
+ if (perf_use_color_default && *color)
r += fprintf(fp, "%s", PERF_COLOR_RESET);
if (trail)
r += fprintf(fp, "%s", trail);
@@ -185,6 +195,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
{
va_list args;
int r;
+
va_start(args, fmt);
r = color_vfprintf(fp, color, fmt, args, NULL);
va_end(args);
commit 8fc0321f1ad0ffef969056dda91b453bbd7a494d
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 15:19:47 2009 +0200
perf_counter tools: Add color terminal output support
Add Git's color printing library to util/color.[ch].
Add it to perf report, with a trivial example to print high-overhead
entries in red, low-overhead entries in green.
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>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index 414399cbc51a..c9ec4585f4d6 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -298,6 +298,7 @@ LIB_H += util/string.h
LIB_H += util/run-command.h
LIB_H += util/sigchain.h
LIB_H += util/symbol.h
+LIB_H += util/color.h
LIB_OBJS += util/abspath.o
LIB_OBJS += util/alias.o
@@ -319,6 +320,7 @@ LIB_OBJS += util/usage.o
LIB_OBJS += util/wrapper.o
LIB_OBJS += util/sigchain.o
LIB_OBJS += util/symbol.o
+LIB_OBJS += util/color.o
LIB_OBJS += util/pager.o
BUILTIN_OBJS += builtin-help.o
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index e930b4e02335..7beedc6effa4 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -9,6 +9,7 @@
#include "util/util.h"
+#include "util/color.h"
#include "util/list.h"
#include "util/cache.h"
#include "util/rbtree.h"
@@ -548,7 +549,19 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
size_t ret;
if (total_samples) {
- ret = fprintf(fp, " %6.2f%%",
+ double percent = self->count * 100.0 / total_samples;
+ char *color = PERF_COLOR_NORMAL;
+
+ /*
+ * We color high-overhead entries in red, low-overhead
+ * entries in green - and keep the middle ground normal:
+ */
+ if (percent >= 5.0)
+ color = PERF_COLOR_RED;
+ if (percent < 0.5)
+ color = PERF_COLOR_GREEN;
+
+ ret = color_fprintf(fp, color, " %6.2f%%",
(self->count * 100.0) / total_samples);
} else
ret = fprintf(fp, "%12d ", self->count);
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 548a8da4b15b..20e5b1200959 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -21,6 +21,7 @@
#include "perf.h"
#include "util/symbol.h"
+#include "util/color.h"
#include "util/util.h"
#include "util/rbtree.h"
#include "util/parse-options.h"
@@ -253,7 +254,8 @@ static void print_sym_table(void)
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
struct symbol *sym = (struct symbol *)(syme + 1);
- float pcnt;
+ char *color = PERF_COLOR_NORMAL;
+ double pcnt;
if (++printed > print_entries || syme->snap_count < count_filter)
continue;
@@ -261,13 +263,22 @@ static void print_sym_table(void)
pcnt = 100.0 - (100.0 * ((sum_kevents - syme->snap_count) /
sum_kevents));
+ /*
+ * We color high-overhead entries in red, low-overhead
+ * entries in green - and keep the middle ground normal:
+ */
+ if (pcnt >= 5.0)
+ color = PERF_COLOR_RED;
+ if (pcnt < 0.5)
+ color = PERF_COLOR_GREEN;
+
if (nr_counters == 1)
- printf("%19.2f - %4.1f%% - %016llx : %s\n",
- syme->weight, pcnt, sym->start, sym->name);
+ printf("%19.2f - ", syme->weight);
else
- printf("%8.1f %10ld - %4.1f%% - %016llx : %s\n",
- syme->weight, syme->snap_count,
- pcnt, sym->start, sym->name);
+ printf("%8.1f %10ld - ", syme->weight, syme->snap_count);
+
+ color_fprintf(stdout, color, "%4.1f%%", pcnt);
+ printf(" - %016llx : %s\n", sym->start, sym->name);
}
{
diff --git a/Documentation/perf_counter/util/color.c b/Documentation/perf_counter/util/color.c
new file mode 100644
index 000000000000..a77975d66774
--- /dev/null
+++ b/Documentation/perf_counter/util/color.c
@@ -0,0 +1,230 @@
+#include "cache.h"
+#include "color.h"
+
+int perf_use_color_default = 0;
+
+static int parse_color(const char *name, int len)
+{
+ static const char * const color_names[] = {
+ "normal", "black", "red", "green", "yellow",
+ "blue", "magenta", "cyan", "white"
+ };
+ char *end;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(color_names); i++) {
+ const char *str = color_names[i];
+ if (!strncasecmp(name, str, len) && !str[len])
+ return i - 1;
+ }
+ i = strtol(name, &end, 10);
+ if (end - name == len && i >= -1 && i <= 255)
+ return i;
+ return -2;
+}
+
+static int parse_attr(const char *name, int len)
+{
+ static const int attr_values[] = { 1, 2, 4, 5, 7 };
+ static const char * const attr_names[] = {
+ "bold", "dim", "ul", "blink", "reverse"
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
+ const char *str = attr_names[i];
+ if (!strncasecmp(name, str, len) && !str[len])
+ return attr_values[i];
+ }
+ return -1;
+}
+
+void color_parse(const char *value, const char *var, char *dst)
+{
+ color_parse_mem(value, strlen(value), var, dst);
+}
+
+void color_parse_mem(const char *value, int value_len, const char *var,
+ char *dst)
+{
+ const char *ptr = value;
+ int len = value_len;
+ int attr = -1;
+ int fg = -2;
+ int bg = -2;
+
+ if (!strncasecmp(value, "reset", len)) {
+ strcpy(dst, PERF_COLOR_RESET);
+ return;
+ }
+
+ /* [fg [bg]] [attr] */
+ while (len > 0) {
+ const char *word = ptr;
+ int val, wordlen = 0;
+
+ while (len > 0 && !isspace(word[wordlen])) {
+ wordlen++;
+ len--;
+ }
+
+ ptr = word + wordlen;
+ while (len > 0 && isspace(*ptr)) {
+ ptr++;
+ len--;
+ }
+
+ val = parse_color(word, wordlen);
+ if (val >= -1) {
+ if (fg == -2) {
+ fg = val;
+ continue;
+ }
+ if (bg == -2) {
+ bg = val;
+ continue;
+ }
+ goto bad;
+ }
+ val = parse_attr(word, wordlen);
+ if (val < 0 || attr != -1)
+ goto bad;
+ attr = val;
+ }
+
+ if (attr >= 0 || fg >= 0 || bg >= 0) {
+ int sep = 0;
+
+ *dst++ = '\033';
+ *dst++ = '[';
+ if (attr >= 0) {
+ *dst++ = '0' + attr;
+ sep++;
+ }
+ if (fg >= 0) {
+ if (sep++)
+ *dst++ = ';';
+ if (fg < 8) {
+ *dst++ = '3';
+ *dst++ = '0' + fg;
+ } else {
+ dst += sprintf(dst, "38;5;%d", fg);
+ }
+ }
+ if (bg >= 0) {
+ if (sep++)
+ *dst++ = ';';
+ if (bg < 8) {
+ *dst++ = '4';
+ *dst++ = '0' + bg;
+ } else {
+ dst += sprintf(dst, "48;5;%d", bg);
+ }
+ }
+ *dst++ = 'm';
+ }
+ *dst = 0;
+ return;
+bad:
+ die("bad color value '%.*s' for variable '%s'", value_len, value, var);
+}
+
+int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
+{
+ if (value) {
+ if (!strcasecmp(value, "never"))
+ return 0;
+ if (!strcasecmp(value, "always"))
+ return 1;
+ if (!strcasecmp(value, "auto"))
+ goto auto_color;
+ }
+
+ /* Missing or explicit false to turn off colorization */
+ if (!perf_config_bool(var, value))
+ return 0;
+
+ /* any normal truth value defaults to 'auto' */
+ auto_color:
+ if (stdout_is_tty < 0)
+ stdout_is_tty = isatty(1);
+ if (stdout_is_tty || (pager_in_use() && pager_use_color)) {
+ char *term = getenv("TERM");
+ if (term && strcmp(term, "dumb"))
+ return 1;
+ }
+ return 0;
+}
+
+int perf_color_default_config(const char *var, const char *value, void *cb)
+{
+ if (!strcmp(var, "color.ui")) {
+ perf_use_color_default = perf_config_colorbool(var, value, -1);
+ return 0;
+ }
+
+ return perf_default_config(var, value, cb);
+}
+
+static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
+ va_list args, const char *trail)
+{
+ int r = 0;
+
+ if (*color)
+ r += fprintf(fp, "%s", color);
+ r += vfprintf(fp, fmt, args);
+ if (*color)
+ r += fprintf(fp, "%s", PERF_COLOR_RESET);
+ if (trail)
+ r += fprintf(fp, "%s", trail);
+ return r;
+}
+
+
+
+int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+ va_start(args, fmt);
+ r = color_vfprintf(fp, color, fmt, args, NULL);
+ va_end(args);
+ return r;
+}
+
+int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+ va_start(args, fmt);
+ r = color_vfprintf(fp, color, fmt, args, "\n");
+ va_end(args);
+ return r;
+}
+
+/*
+ * This function splits the buffer by newlines and colors the lines individually.
+ *
+ * Returns 0 on success.
+ */
+int color_fwrite_lines(FILE *fp, const char *color,
+ size_t count, const char *buf)
+{
+ if (!*color)
+ return fwrite(buf, count, 1, fp) != 1;
+ while (count) {
+ char *p = memchr(buf, '\n', count);
+ if (p != buf && (fputs(color, fp) < 0 ||
+ fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
+ fputs(PERF_COLOR_RESET, fp) < 0))
+ return -1;
+ if (!p)
+ return 0;
+ if (fputc('\n', fp) < 0)
+ return -1;
+ count -= p + 1 - buf;
+ buf = p + 1;
+ }
+ return 0;
+}
+
+
diff --git a/Documentation/perf_counter/util/color.h b/Documentation/perf_counter/util/color.h
new file mode 100644
index 000000000000..5abfd379582b
--- /dev/null
+++ b/Documentation/perf_counter/util/color.h
@@ -0,0 +1,36 @@
+#ifndef COLOR_H
+#define COLOR_H
+
+/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
+#define COLOR_MAXLEN 24
+
+#define PERF_COLOR_NORMAL ""
+#define PERF_COLOR_RESET "\033[m"
+#define PERF_COLOR_BOLD "\033[1m"
+#define PERF_COLOR_RED "\033[31m"
+#define PERF_COLOR_GREEN "\033[32m"
+#define PERF_COLOR_YELLOW "\033[33m"
+#define PERF_COLOR_BLUE "\033[34m"
+#define PERF_COLOR_MAGENTA "\033[35m"
+#define PERF_COLOR_CYAN "\033[36m"
+#define PERF_COLOR_BG_RED "\033[41m"
+
+/*
+ * This variable stores the value of color.ui
+ */
+extern int perf_use_color_default;
+
+
+/*
+ * Use this instead of perf_default_config if you need the value of color.ui.
+ */
+int perf_color_default_config(const char *var, const char *value, void *cb);
+
+int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
+void color_parse(const char *value, const char *var, char *dst);
+void color_parse_mem(const char *value, int len, const char *var, char *dst);
+int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
+int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
+int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
+
+#endif /* COLOR_H */
diff --git a/Documentation/perf_counter/util/environment.c b/Documentation/perf_counter/util/environment.c
index 9b1c8199e729..275b0ee345f5 100644
--- a/Documentation/perf_counter/util/environment.c
+++ b/Documentation/perf_counter/util/environment.c
@@ -6,3 +6,4 @@
#include "cache.h"
const char *pager_program;
+int pager_use_color = 1;