diff options
Diffstat (limited to 'tools/perf/builtin-diff.c')
-rw-r--r-- | tools/perf/builtin-diff.c | 90 |
1 files changed, 19 insertions, 71 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index ff91e9c291bb..66f100d249a8 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -16,10 +16,10 @@ | |||
16 | 16 | ||
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | 18 | ||
19 | static char const *input_old = "perf.data.old", | 19 | static char const *input_old = "perf.data.old", |
20 | *input_new = "perf.data"; | 20 | *input_new = "perf.data"; |
21 | static int force; | 21 | static int force; |
22 | static bool show_percent; | 22 | static bool show_displacement; |
23 | 23 | ||
24 | static int perf_session__add_hist_entry(struct perf_session *self, | 24 | static int perf_session__add_hist_entry(struct perf_session *self, |
25 | struct addr_location *al, u64 count) | 25 | struct addr_location *al, u64 count) |
@@ -162,70 +162,6 @@ static void perf_session__match_hists(struct perf_session *old_session, | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | static size_t hist_entry__fprintf_matched(struct hist_entry *self, | ||
166 | unsigned long pos, | ||
167 | struct perf_session *session, | ||
168 | struct perf_session *pair_session, | ||
169 | FILE *fp) | ||
170 | { | ||
171 | u64 old_count = 0; | ||
172 | char displacement[16]; | ||
173 | size_t printed; | ||
174 | |||
175 | if (self->pair != NULL) { | ||
176 | long pdiff = (long)self->pair->position - (long)pos; | ||
177 | old_count = self->pair->count; | ||
178 | if (pdiff == 0) | ||
179 | goto blank; | ||
180 | snprintf(displacement, sizeof(displacement), "%+4ld", pdiff); | ||
181 | } else { | ||
182 | blank: memset(displacement, ' ', sizeof(displacement)); | ||
183 | } | ||
184 | |||
185 | printed = fprintf(fp, "%4lu %5.5s ", pos, displacement); | ||
186 | |||
187 | if (show_percent) { | ||
188 | double old_percent = 0, new_percent = 0, diff; | ||
189 | |||
190 | if (pair_session->events_stats.total > 0) | ||
191 | old_percent = (old_count * 100) / pair_session->events_stats.total; | ||
192 | if (session->events_stats.total > 0) | ||
193 | new_percent = (self->count * 100) / session->events_stats.total; | ||
194 | |||
195 | diff = old_percent - new_percent; | ||
196 | if (verbose) | ||
197 | printed += fprintf(fp, " %3.2f%% %3.2f%%", old_percent, new_percent); | ||
198 | |||
199 | if ((u64)diff != 0) | ||
200 | printed += fprintf(fp, " %+4.2F%%", diff); | ||
201 | else | ||
202 | printed += fprintf(fp, " "); | ||
203 | } else { | ||
204 | if (verbose) | ||
205 | printed += fprintf(fp, " %9Lu %9Lu", old_count, self->count); | ||
206 | printed += fprintf(fp, " %+9Ld", (s64)self->count - (s64)old_count); | ||
207 | } | ||
208 | |||
209 | return printed + fprintf(fp, " %25.25s %s\n", | ||
210 | self->map->dso->name, self->sym->name); | ||
211 | } | ||
212 | |||
213 | static size_t perf_session__fprintf_matched_hists(struct perf_session *self, | ||
214 | struct perf_session *pair, | ||
215 | FILE *fp) | ||
216 | { | ||
217 | struct rb_node *nd; | ||
218 | size_t printed = 0; | ||
219 | unsigned long pos = 1; | ||
220 | |||
221 | for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { | ||
222 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | ||
223 | printed += hist_entry__fprintf_matched(he, pos++, self, pair, fp); | ||
224 | } | ||
225 | |||
226 | return printed; | ||
227 | } | ||
228 | |||
229 | static int __cmd_diff(void) | 165 | static int __cmd_diff(void) |
230 | { | 166 | { |
231 | int ret, i; | 167 | int ret, i; |
@@ -244,7 +180,8 @@ static int __cmd_diff(void) | |||
244 | } | 180 | } |
245 | 181 | ||
246 | perf_session__match_hists(session[0], session[1]); | 182 | perf_session__match_hists(session[0], session[1]); |
247 | perf_session__fprintf_matched_hists(session[1], session[0], stdout); | 183 | perf_session__fprintf_hists(session[1], session[0], |
184 | show_displacement, stdout); | ||
248 | out_delete: | 185 | out_delete: |
249 | for (i = 0; i < 2; ++i) | 186 | for (i = 0; i < 2; ++i) |
250 | perf_session__delete(session[i]); | 187 | perf_session__delete(session[i]); |
@@ -258,13 +195,13 @@ static const char *const diff_usage[] = { | |||
258 | static const struct option options[] = { | 195 | static const struct option options[] = { |
259 | OPT_BOOLEAN('v', "verbose", &verbose, | 196 | OPT_BOOLEAN('v', "verbose", &verbose, |
260 | "be more verbose (show symbol address, etc)"), | 197 | "be more verbose (show symbol address, etc)"), |
198 | OPT_BOOLEAN('m', "displacement", &show_displacement, | ||
199 | "Show position displacement relative to baseline"), | ||
261 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 200 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
262 | "dump raw trace in ASCII"), | 201 | "dump raw trace in ASCII"), |
263 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), | 202 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), |
264 | OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, | 203 | OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, |
265 | "load module symbols - WARNING: use only with -k and LIVE kernel"), | 204 | "load module symbols - WARNING: use only with -k and LIVE kernel"), |
266 | OPT_BOOLEAN('p', "percentages", &show_percent, | ||
267 | "Don't shorten the pathnames taking into account the cwd"), | ||
268 | OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths, | 205 | OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths, |
269 | "Don't shorten the pathnames taking into account the cwd"), | 206 | "Don't shorten the pathnames taking into account the cwd"), |
270 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", | 207 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", |
@@ -273,6 +210,11 @@ static const struct option options[] = { | |||
273 | "only consider symbols in these comms"), | 210 | "only consider symbols in these comms"), |
274 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | 211 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", |
275 | "only consider these symbols"), | 212 | "only consider these symbols"), |
213 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | ||
214 | "sort by key(s): pid, comm, dso, symbol, parent"), | ||
215 | OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", | ||
216 | "separator for columns, no spaces will be added between " | ||
217 | "columns '.' is reserved."), | ||
276 | OPT_END() | 218 | OPT_END() |
277 | }; | 219 | }; |
278 | 220 | ||
@@ -289,10 +231,16 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used) | |||
289 | input_new = argv[0]; | 231 | input_new = argv[0]; |
290 | } | 232 | } |
291 | 233 | ||
234 | symbol_conf.exclude_other = false; | ||
292 | if (symbol__init() < 0) | 235 | if (symbol__init() < 0) |
293 | return -1; | 236 | return -1; |
294 | 237 | ||
295 | setup_sorting(diff_usage, options); | 238 | setup_sorting(diff_usage, options); |
296 | setup_pager(); | 239 | setup_pager(); |
240 | |||
241 | sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", NULL); | ||
242 | sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", NULL); | ||
243 | sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", NULL); | ||
244 | |||
297 | return __cmd_diff(); | 245 | return __cmd_diff(); |
298 | } | 246 | } |