aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-diff.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-diff.c')
-rw-r--r--tools/perf/builtin-diff.c96
1 files changed, 63 insertions, 33 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index d29d350fb2b7..761f4197a9e2 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -10,6 +10,7 @@
10#include "util/event.h" 10#include "util/event.h"
11#include "util/hist.h" 11#include "util/hist.h"
12#include "util/evsel.h" 12#include "util/evsel.h"
13#include "util/evlist.h"
13#include "util/session.h" 14#include "util/session.h"
14#include "util/tool.h" 15#include "util/tool.h"
15#include "util/sort.h" 16#include "util/sort.h"
@@ -24,11 +25,6 @@ static char diff__default_sort_order[] = "dso,symbol";
24static bool force; 25static bool force;
25static bool show_displacement; 26static bool show_displacement;
26 27
27struct perf_diff {
28 struct perf_tool tool;
29 struct perf_session *session;
30};
31
32static int hists__add_entry(struct hists *self, 28static int hists__add_entry(struct hists *self,
33 struct addr_location *al, u64 period) 29 struct addr_location *al, u64 period)
34{ 30{
@@ -37,14 +33,12 @@ static int hists__add_entry(struct hists *self,
37 return -ENOMEM; 33 return -ENOMEM;
38} 34}
39 35
40static int diff__process_sample_event(struct perf_tool *tool, 36static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
41 union perf_event *event, 37 union perf_event *event,
42 struct perf_sample *sample, 38 struct perf_sample *sample,
43 struct perf_evsel *evsel __used, 39 struct perf_evsel *evsel,
44 struct machine *machine) 40 struct machine *machine)
45{ 41{
46 struct perf_diff *_diff = container_of(tool, struct perf_diff, tool);
47 struct perf_session *session = _diff->session;
48 struct addr_location al; 42 struct addr_location al;
49 43
50 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { 44 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
@@ -56,26 +50,24 @@ static int diff__process_sample_event(struct perf_tool *tool,
56 if (al.filtered || al.sym == NULL) 50 if (al.filtered || al.sym == NULL)
57 return 0; 51 return 0;
58 52
59 if (hists__add_entry(&session->hists, &al, sample->period)) { 53 if (hists__add_entry(&evsel->hists, &al, sample->period)) {
60 pr_warning("problem incrementing symbol period, skipping event\n"); 54 pr_warning("problem incrementing symbol period, skipping event\n");
61 return -1; 55 return -1;
62 } 56 }
63 57
64 session->hists.stats.total_period += sample->period; 58 evsel->hists.stats.total_period += sample->period;
65 return 0; 59 return 0;
66} 60}
67 61
68static struct perf_diff diff = { 62static struct perf_tool tool = {
69 .tool = { 63 .sample = diff__process_sample_event,
70 .sample = diff__process_sample_event, 64 .mmap = perf_event__process_mmap,
71 .mmap = perf_event__process_mmap, 65 .comm = perf_event__process_comm,
72 .comm = perf_event__process_comm, 66 .exit = perf_event__process_task,
73 .exit = perf_event__process_task, 67 .fork = perf_event__process_task,
74 .fork = perf_event__process_task, 68 .lost = perf_event__process_lost,
75 .lost = perf_event__process_lost, 69 .ordered_samples = true,
76 .ordered_samples = true, 70 .ordering_requires_timestamps = true,
77 .ordering_requires_timestamps = true,
78 },
79}; 71};
80 72
81static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 73static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -146,34 +138,71 @@ static void hists__match(struct hists *older, struct hists *newer)
146 } 138 }
147} 139}
148 140
141static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
142 struct perf_evlist *evlist)
143{
144 struct perf_evsel *e;
145
146 list_for_each_entry(e, &evlist->entries, node)
147 if (perf_evsel__match2(evsel, e))
148 return e;
149
150 return NULL;
151}
152
149static int __cmd_diff(void) 153static int __cmd_diff(void)
150{ 154{
151 int ret, i; 155 int ret, i;
152#define older (session[0]) 156#define older (session[0])
153#define newer (session[1]) 157#define newer (session[1])
154 struct perf_session *session[2]; 158 struct perf_session *session[2];
159 struct perf_evlist *evlist_new, *evlist_old;
160 struct perf_evsel *evsel;
161 bool first = true;
155 162
156 older = perf_session__new(input_old, O_RDONLY, force, false, 163 older = perf_session__new(input_old, O_RDONLY, force, false,
157 &diff.tool); 164 &tool);
158 newer = perf_session__new(input_new, O_RDONLY, force, false, 165 newer = perf_session__new(input_new, O_RDONLY, force, false,
159 &diff.tool); 166 &tool);
160 if (session[0] == NULL || session[1] == NULL) 167 if (session[0] == NULL || session[1] == NULL)
161 return -ENOMEM; 168 return -ENOMEM;
162 169
163 for (i = 0; i < 2; ++i) { 170 for (i = 0; i < 2; ++i) {
164 diff.session = session[i]; 171 ret = perf_session__process_events(session[i], &tool);
165 ret = perf_session__process_events(session[i], &diff.tool);
166 if (ret) 172 if (ret)
167 goto out_delete; 173 goto out_delete;
168 hists__output_resort(&session[i]->hists);
169 } 174 }
170 175
171 if (show_displacement) 176 evlist_old = older->evlist;
172 hists__resort_entries(&older->hists); 177 evlist_new = newer->evlist;
178
179 list_for_each_entry(evsel, &evlist_new->entries, node)
180 hists__output_resort(&evsel->hists);
181
182 list_for_each_entry(evsel, &evlist_old->entries, node) {
183 hists__output_resort(&evsel->hists);
184
185 if (show_displacement)
186 hists__resort_entries(&evsel->hists);
187 }
188
189 list_for_each_entry(evsel, &evlist_new->entries, node) {
190 struct perf_evsel *evsel_old;
191
192 evsel_old = evsel_match(evsel, evlist_old);
193 if (!evsel_old)
194 continue;
195
196 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
197 perf_evsel__name(evsel));
198
199 first = false;
200
201 hists__match(&evsel_old->hists, &evsel->hists);
202 hists__fprintf(&evsel->hists, &evsel_old->hists,
203 show_displacement, true, 0, 0, stdout);
204 }
173 205
174 hists__match(&older->hists, &newer->hists);
175 hists__fprintf(&newer->hists, &older->hists,
176 show_displacement, true, 0, 0, stdout);
177out_delete: 206out_delete:
178 for (i = 0; i < 2; ++i) 207 for (i = 0; i < 2; ++i)
179 perf_session__delete(session[i]); 208 perf_session__delete(session[i]);
@@ -213,7 +242,7 @@ static const struct option options[] = {
213 OPT_END() 242 OPT_END()
214}; 243};
215 244
216int cmd_diff(int argc, const char **argv, const char *prefix __used) 245int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
217{ 246{
218 sort_order = diff__default_sort_order; 247 sort_order = diff__default_sort_order;
219 argc = parse_options(argc, argv, options, diff_usage, 0); 248 argc = parse_options(argc, argv, options, diff_usage, 0);
@@ -235,6 +264,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used)
235 if (symbol__init() < 0) 264 if (symbol__init() < 0)
236 return -1; 265 return -1;
237 266
267 perf_hpp__init(true, show_displacement);
238 setup_sorting(diff_usage, options); 268 setup_sorting(diff_usage, options);
239 setup_pager(); 269 setup_pager();
240 270