aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorBrice Goglin <Brice.Goglin@inria.fr>2009-08-07 07:55:24 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-09 07:04:20 -0400
commit8d51327090ac025d7f4ce6c059786b5e93513321 (patch)
tree32576a197af970ac698c7888c67235e8f723fa67 /tools/perf/util
parent30dd568c912602b7dbd609a45d053e01b13422bb (diff)
perf report: Fix and improve the displaying of per-thread event counters
Improve and fix the handling of per-thread counter stats recorded via perf record -s. Previously we only displayed it in debug printouts (-D) and even that output was hard to disambiguate. I moved everything to utils/values.[ch] so that we may reuse it in perf stat. We get something like this now: # PID TID cache-misses cache-references 4658 4659 495581 3238779 4658 4662 498246 3236823 4658 4663 499531 3243162 Then it'll be easy to add --pretty=raw to display a single line per thread/event. By the way, -S was also used for --symbol... So I used -T/--thread here. perf report: Add -T/--threads to display per-thread counter values We get something like this now: # PID TID cache-misses cache-references 4658 4659 495581 3238779 4658 4662 498246 3236823 4658 4663 499531 3243162 Per-thread arrays of counter values are managed in utils/values.[ch] Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: paulus@samba.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/values.c171
-rw-r--r--tools/perf/util/values.h26
2 files changed, 197 insertions, 0 deletions
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
new file mode 100644
index 000000000000..8551c0b8b233
--- /dev/null
+++ b/tools/perf/util/values.c
@@ -0,0 +1,171 @@
1#include <stdlib.h>
2
3#include "util.h"
4#include "values.h"
5
6void perf_read_values_init(struct perf_read_values *values)
7{
8 values->threads_max = 16;
9 values->pid = malloc(values->threads_max * sizeof(*values->pid));
10 values->tid = malloc(values->threads_max * sizeof(*values->tid));
11 values->value = malloc(values->threads_max * sizeof(*values->value));
12 if (!values->pid || !values->tid || !values->value)
13 die("failed to allocate read_values threads arrays");
14 values->threads = 0;
15
16 values->counters_max = 16;
17 values->counterrawid = malloc(values->counters_max
18 * sizeof(*values->counterrawid));
19 values->countername = malloc(values->counters_max
20 * sizeof(*values->countername));
21 if (!values->counterrawid || !values->countername)
22 die("failed to allocate read_values counters arrays");
23 values->counters = 0;
24}
25
26void perf_read_values_destroy(struct perf_read_values *values)
27{
28 int i;
29
30 if (!values->threads_max || !values->counters_max)
31 return;
32
33 for (i = 0; i < values->threads; i++)
34 free(values->value[i]);
35 free(values->pid);
36 free(values->tid);
37 free(values->counterrawid);
38 for (i = 0; i < values->counters; i++)
39 free(values->countername[i]);
40 free(values->countername);
41}
42
43static void perf_read_values__enlarge_threads(struct perf_read_values *values)
44{
45 values->threads_max *= 2;
46 values->pid = realloc(values->pid,
47 values->threads_max * sizeof(*values->pid));
48 values->tid = realloc(values->tid,
49 values->threads_max * sizeof(*values->tid));
50 values->value = realloc(values->value,
51 values->threads_max * sizeof(*values->value));
52 if (!values->pid || !values->tid || !values->value)
53 die("failed to enlarge read_values threads arrays");
54}
55
56static int perf_read_values__findnew_thread(struct perf_read_values *values,
57 u32 pid, u32 tid)
58{
59 int i;
60
61 for (i = 0; i < values->threads; i++)
62 if (values->pid[i] == pid && values->tid[i] == tid)
63 return i;
64
65 if (values->threads == values->threads_max)
66 perf_read_values__enlarge_threads(values);
67
68 i = values->threads++;
69 values->pid[i] = pid;
70 values->tid[i] = tid;
71 values->value[i] = malloc(values->counters_max * sizeof(**values->value));
72 if (!values->value[i])
73 die("failed to allocate read_values counters array");
74
75 return i;
76}
77
78static void perf_read_values__enlarge_counters(struct perf_read_values *values)
79{
80 int i;
81
82 values->counters_max *= 2;
83 values->counterrawid = realloc(values->counterrawid,
84 values->counters_max * sizeof(*values->counterrawid));
85 values->countername = realloc(values->countername,
86 values->counters_max * sizeof(*values->countername));
87 if (!values->counterrawid || !values->countername)
88 die("failed to enlarge read_values counters arrays");
89
90 for (i = 0; i < values->threads; i++) {
91 values->value[i] = realloc(values->value[i],
92 values->counters_max * sizeof(**values->value));
93 if (!values->value[i])
94 die("failed to enlarge read_values counters arrays");
95 }
96}
97
98static int perf_read_values__findnew_counter(struct perf_read_values *values,
99 u64 rawid, char *name)
100{
101 int i;
102
103 for (i = 0; i < values->counters; i++)
104 if (values->counterrawid[i] == rawid)
105 return i;
106
107 if (values->counters == values->counters_max)
108 perf_read_values__enlarge_counters(values);
109
110 i = values->counters++;
111 values->counterrawid[i] = rawid;
112 values->countername[i] = strdup(name);
113
114 return i;
115}
116
117void perf_read_values_add_value(struct perf_read_values *values,
118 u32 pid, u32 tid,
119 u64 rawid, char *name, u64 value)
120{
121 int tindex, cindex;
122
123 tindex = perf_read_values__findnew_thread(values, pid, tid);
124 cindex = perf_read_values__findnew_counter(values, rawid, name);
125
126 values->value[tindex][cindex] = value;
127}
128
129void perf_read_values_display(FILE *fp, struct perf_read_values *values)
130{
131 int i, j;
132 int pidwidth, tidwidth;
133 int *counterwidth;
134
135 counterwidth = malloc(values->counters * sizeof(*counterwidth));
136 if (!counterwidth)
137 die("failed to allocate counterwidth array");
138 tidwidth = 3;
139 pidwidth = 3;
140 for (j = 0; j < values->counters; j++)
141 counterwidth[j] = strlen(values->countername[j]);
142 for (i = 0; i < values->threads; i++) {
143 int width;
144
145 width = snprintf(NULL, 0, "%d", values->pid[i]);
146 if (width > pidwidth)
147 pidwidth = width;
148 width = snprintf(NULL, 0, "%d", values->tid[i]);
149 if (width > tidwidth)
150 tidwidth = width;
151 for (j = 0; j < values->counters; j++) {
152 width = snprintf(NULL, 0, "%Lu", values->value[i][j]);
153 if (width > counterwidth[j])
154 counterwidth[j] = width;
155 }
156 }
157
158 fprintf(fp, "# %*s %*s", pidwidth, "PID", tidwidth, "TID");
159 for (j = 0; j < values->counters; j++)
160 fprintf(fp, " %*s", counterwidth[j], values->countername[j]);
161 fprintf(fp, "\n");
162
163 for (i = 0; i < values->threads; i++) {
164 fprintf(fp, " %*d %*d", pidwidth, values->pid[i],
165 tidwidth, values->tid[i]);
166 for (j = 0; j < values->counters; j++)
167 fprintf(fp, " %*Lu",
168 counterwidth[j], values->value[i][j]);
169 fprintf(fp, "\n");
170 }
171}
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
new file mode 100644
index 000000000000..e41be5e86e6b
--- /dev/null
+++ b/tools/perf/util/values.h
@@ -0,0 +1,26 @@
1#ifndef _PERF_VALUES_H
2#define _PERF_VALUES_H
3
4#include "types.h"
5
6struct perf_read_values {
7 int threads;
8 int threads_max;
9 u32 *pid, *tid;
10 int counters;
11 int counters_max;
12 u64 *counterrawid;
13 char **countername;
14 u64 **value;
15};
16
17void perf_read_values_init(struct perf_read_values *values);
18void perf_read_values_destroy(struct perf_read_values *values);
19
20void perf_read_values_add_value(struct perf_read_values *values,
21 u32 pid, u32 tid,
22 u64 rawid, char *name, u64 value);
23
24void perf_read_values_display(FILE *fp, struct perf_read_values *values);
25
26#endif /* _PERF_VALUES_H */