Skip to content

Commit

Permalink
perf diff: Use perf_session__fprintf_hists just like 'perf record'
Browse files Browse the repository at this point in the history
That means that almost everything you can do with 'perf report'
can be done with 'perf diff', for instance:

$ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2699
samples) ] $ perf record -f find / > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.062 MB perf.data (~2687
samples) ] perf diff | head -8
     9.02%     +1.00%     find  libc-2.10.1.so               [.] _IO_vfprintf_internal
     2.91%     -1.00%     find  [kernel]                     [k] __kmalloc
     2.85%     -1.00%     find  [kernel]                     [k] ext4_htree_store_dirent
     1.99%     -1.00%     find  [kernel]                     [k] _atomic_dec_and_lock
     2.44%                find  [kernel]                     [k] half_md4_transform
$

So if you want to zoom into libc:

$ perf diff --dsos libc-2.10.1.so | head -8
    37.34%                find  [.] _IO_vfprintf_internal
    10.34%                find  [.] __GI_memmove
     8.25%     +2.00%     find  [.] _int_malloc
     5.07%     -1.00%     find  [.] __GI_mempcpy
     7.62%     +2.00%     find  [.] _int_free
$

And if there were multiple commands using libc, it is also
possible to aggregate them all by using --sort symbol:

$ perf diff --dsos libc-2.10.1.so --sort symbol | head -8
    37.34%             [.] _IO_vfprintf_internal
    10.34%             [.] __GI_memmove
     8.25%     +2.00%  [.] _int_malloc
     5.07%     -1.00%  [.] __GI_mempcpy
     7.62%     +2.00%  [.] _int_free
$

The displacement column now is off by default, to use it:

perf diff -m --dsos libc-2.10.1.so --sort symbol | head -8
    37.34%                   [.] _IO_vfprintf_internal
    10.34%                   [.] __GI_memmove
     8.25%     +2.00%        [.] _int_malloc
     5.07%     -1.00%    +2  [.] __GI_mempcpy
     7.62%     +2.00%    -1  [.] _int_free
$

Using -t/--field-separator can be used for scripting:

$ perf diff -t, -m --dsos libc-2.10.1.so --sort symbol | head -8
37.34, , ,[.] _IO_vfprintf_internal
10.34, , ,[.] __GI_memmove
8.25,+2.00%, ,[.] _int_malloc
5.07,-1.00%,  +2,[.] __GI_mempcpy
7.62,+2.00%,  -1,[.] _int_free
6.99,+1.00%,  -1,[.] _IO_new_file_xsputn
1.89,-2.00%,  +4,[.] __readdir64
$

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frédéric Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
acmel authored and Ingo Molnar committed Dec 16, 2009
1 parent 125c4fa commit c351c28
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 110 deletions.
29 changes: 26 additions & 3 deletions tools/perf/Documentation/perf-diff.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,32 @@ If no parameters are passed it will assume perf.data.old and perf.data.

OPTIONS
-------
-p::
--percentage::
Show percentages instead of raw counts
-d::
--dsos=::
Only consider symbols in these dsos. CSV that understands
file://filename entries.

-C::
--comms=::
Only consider symbols in these comms. CSV that understands
file://filename entries.

-S::
--symbols=::
Only consider these symbols. CSV that understands
file://filename entries.

-s::
--sort=::
Sort by key(s): pid, comm, dso, symbol.

-t::
--field-separator=::

Use a special separator character and don't pad with spaces, replacing
all occurances of this separator in symbol names (and other output)
with a '.' character, that thus it's the only non valid separator.

-v::
--verbose::
Be verbose, for instance, show the raw counts in addition to the
Expand Down
4 changes: 4 additions & 0 deletions tools/perf/Documentation/perf-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ OPTIONS
Only consider these symbols. CSV that understands
file://filename entries.

-s::
--sort=::
Sort by key(s): pid, comm, dso, symbol, parent.

-w::
--field-width=::
Force each column width to the provided list, for large terminal
Expand Down
90 changes: 19 additions & 71 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

#include <stdlib.h>

static char const *input_old = "perf.data.old",
*input_new = "perf.data";
static int force;
static bool show_percent;
static char const *input_old = "perf.data.old",
*input_new = "perf.data";
static int force;
static bool show_displacement;

static int perf_session__add_hist_entry(struct perf_session *self,
struct addr_location *al, u64 count)
Expand Down Expand Up @@ -162,70 +162,6 @@ static void perf_session__match_hists(struct perf_session *old_session,
}
}

static size_t hist_entry__fprintf_matched(struct hist_entry *self,
unsigned long pos,
struct perf_session *session,
struct perf_session *pair_session,
FILE *fp)
{
u64 old_count = 0;
char displacement[16];
size_t printed;

if (self->pair != NULL) {
long pdiff = (long)self->pair->position - (long)pos;
old_count = self->pair->count;
if (pdiff == 0)
goto blank;
snprintf(displacement, sizeof(displacement), "%+4ld", pdiff);
} else {
blank: memset(displacement, ' ', sizeof(displacement));
}

printed = fprintf(fp, "%4lu %5.5s ", pos, displacement);

if (show_percent) {
double old_percent = 0, new_percent = 0, diff;

if (pair_session->events_stats.total > 0)
old_percent = (old_count * 100) / pair_session->events_stats.total;
if (session->events_stats.total > 0)
new_percent = (self->count * 100) / session->events_stats.total;

diff = old_percent - new_percent;
if (verbose)
printed += fprintf(fp, " %3.2f%% %3.2f%%", old_percent, new_percent);

if ((u64)diff != 0)
printed += fprintf(fp, " %+4.2F%%", diff);
else
printed += fprintf(fp, " ");
} else {
if (verbose)
printed += fprintf(fp, " %9Lu %9Lu", old_count, self->count);
printed += fprintf(fp, " %+9Ld", (s64)self->count - (s64)old_count);
}

return printed + fprintf(fp, " %25.25s %s\n",
self->map->dso->name, self->sym->name);
}

static size_t perf_session__fprintf_matched_hists(struct perf_session *self,
struct perf_session *pair,
FILE *fp)
{
struct rb_node *nd;
size_t printed = 0;
unsigned long pos = 1;

for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
printed += hist_entry__fprintf_matched(he, pos++, self, pair, fp);
}

return printed;
}

static int __cmd_diff(void)
{
int ret, i;
Expand All @@ -244,7 +180,8 @@ static int __cmd_diff(void)
}

perf_session__match_hists(session[0], session[1]);
perf_session__fprintf_matched_hists(session[1], session[0], stdout);
perf_session__fprintf_hists(session[1], session[0],
show_displacement, stdout);
out_delete:
for (i = 0; i < 2; ++i)
perf_session__delete(session[i]);
Expand All @@ -258,13 +195,13 @@ static const char *const diff_usage[] = {
static const struct option options[] = {
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('m', "displacement", &show_displacement,
"Show position displacement relative to baseline"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
"load module symbols - WARNING: use only with -k and LIVE kernel"),
OPT_BOOLEAN('p', "percentages", &show_percent,
"Don't shorten the pathnames taking into account the cwd"),
OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths,
"Don't shorten the pathnames taking into account the cwd"),
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
Expand All @@ -273,6 +210,11 @@ static const struct option options[] = {
"only consider symbols in these comms"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
"only consider these symbols"),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
"sort by key(s): pid, comm, dso, symbol, parent"),
OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
"separator for columns, no spaces will be added between "
"columns '.' is reserved."),
OPT_END()
};

Expand All @@ -289,10 +231,16 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used)
input_new = argv[0];
}

symbol_conf.exclude_other = false;
if (symbol__init() < 0)
return -1;

setup_sorting(diff_usage, options);
setup_pager();

sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", NULL);
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", NULL);
sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", NULL);

return __cmd_diff();
}
12 changes: 1 addition & 11 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ static int __cmd_report(void)
perf_session__collapse_resort(session);
perf_session__output_resort(session, session->events_stats.total);
fprintf(stdout, "# Samples: %ld\n#\n", session->events_stats.total);
perf_session__fprintf_hists(session, stdout);
perf_session__fprintf_hists(session, NULL, false, stdout);
if (sort_order == default_sort_order &&
parent_pattern == default_parent_pattern)
fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n");
Expand Down Expand Up @@ -344,16 +344,6 @@ static const struct option options[] = {
OPT_END()
};

static void sort_entry__setup_elide(struct sort_entry *self,
struct strlist *list,
const char *list_name, FILE *fp)
{
if (list && strlist__nr_entries(list) == 1) {
fprintf(fp, "# %s: %s\n", list_name, strlist__entry(list, 0)->s);
self->elide = true;
}
}

int cmd_report(int argc, const char **argv, const char *prefix __used)
{
argc = parse_options(argc, argv, options, report_usage, 0);
Expand Down
Loading

0 comments on commit c351c28

Please sign in to comment.