perf report: Add support for srcfile sort key

This change “perf report: Add support for srcfile sort key” in Linux kernel is authored by Andi Kleen <ak [at] linux.intel.com> on Fri Aug 7 15:54:24 2015 -0700.

perf report: Add support for srcfile sort key

In some cases it's useful to characterize samples by file. This is
useful to get a higher level categorization, for example to map cost to
subsystems.

Add a srcfile sort key to perf report. It builds on top of the existing
srcline support.

Commiter notes:

E.g.:

  # perf record -F 10000 usleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.016 MB perf.data (13 samples) ]
  [root@zoo ~]# perf report -s srcfile --stdio
  # Total Lost Samples: 0
  #
  # Samples: 13  of event 'cycles'
  # Event count (approx.): 869878
  #
  # Overhead  Source File
  # ........  ...........
      60.99%  .
      20.62%  paravirt.h
      14.23%  rmap.c
       4.04%  signal.c
       0.11%  msr.h

  #

The first line is collecting all the files for which srcfiles couldn't somehow
get resolved to:

  # perf report -s srcfile,dso --stdio
  # Total Lost Samples: 0
  #
  # Samples: 13  of event 'cycles'
  # Event count (approx.): 869878
  #
  # Overhead  Source File  Shared Object
  # ........  ...........  ................
      40.97%  .            ld-2.20.so
      20.62%  paravirt.h   [kernel.vmlinux]
      20.02%  .            libc-2.20.so
      14.23%  rmap.c       [kernel.vmlinux]
       4.04%  signal.c     [kernel.vmlinux]
       0.11%  msr.h        [kernel.vmlinux]

  #

XXX: Investigate why that is not resolving on Fedora 21, Andi says he hasn't
     seen this on Fedora 22.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1438988064-21834-1-git-send-email-andi@firstfloor.org
[ Added column length update, from 0e65bdb3f90f ('perf hists: Update the column width for the "srcline" sort key') ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

This Linux change may have been applied to various maintained Linux releases and you can find Linux releases including commit 31191a8.

There are 62 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 tools/perf/Documentation/perf-report.txt |  2 ++
 tools/perf/util/hist.c                   |  5 +++
 tools/perf/util/hist.h                   |  1 +
 tools/perf/util/sort.c                   | 52 ++++++++++++++++++++++++++++++++
 tools/perf/util/sort.h                   |  2 ++
 5 files changed, 62 insertions(+)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 1a782ef..7b07d19 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -81,6 +81,8 @@ OPTIONS
 	- cpu: cpu number the task ran at the time of sample
 	- srcline: filename and line number executed at the time of sample.  The
 	DWARF debugging info must be provided.
+	- srcfile: file name of the source file of the same. Requires dwarf
+	information.
 	- weight: Event specific weight, e.g. memory latency or transaction
 	abort cost. This is the global weight.
 	- local_weight: Local weight version of the weight above.
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 608c0a7..6bccfae 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -154,6 +154,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
 	if (h->srcline)
 		hists__new_col_len(hists, HISTC_SRCLINE, strlen(h->srcline));
 
+	if (h->srcfile)
+		hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile));
+
 	if (h->transaction)
 		hists__new_col_len(hists, HISTC_TRANSACTION,
 				   hist_entry__transaction_len());
@@ -949,6 +952,8 @@ void hist_entry__delete(struct hist_entry *he)
 
 	zfree(&he->stat_acc);
 	free_srcline(he->srcline);
+	if (he->srcfile && he->srcfile[0])
+		free(he->srcfile);
 	free_callchain(he->callchain);
 	free(he);
 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index e2f712f..bc528d5 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -30,6 +30,7 @@ enum hist_column {
 	HISTC_PARENT,
 	HISTC_CPU,
 	HISTC_SRCLINE,
+	HISTC_SRCFILE,
 	HISTC_MISPREDICT,
 	HISTC_IN_TX,
 	HISTC_ABORT,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5177088..c0c32b0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -319,6 +319,57 @@ struct sort_entry sort_srcline = {
 	.se_width_idx	= HISTC_SRCLINE,
 };
 
+/* --sort srcfile */
+
+static char no_srcfile[1];
+
+static char *get_srcfile(struct hist_entry *e)
+{
+	char *sf, *p;
+	struct map *map = e->ms.map;
+
+	sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip),
+			 e->ms.sym, true);
+	p = strchr(sf, ':');
+	if (p && *sf) {
+		*p = 0;
+		return sf;
+	}
+	free(sf);
+	return no_srcfile;
+}
+
+static int64_t
+sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	if (!left->srcfile) {
+		if (!left->ms.map)
+			left->srcfile = no_srcfile;
+		else
+			left->srcfile = get_srcfile(left);
+	}
+	if (!right->srcfile) {
+		if (!right->ms.map)
+			right->srcfile = no_srcfile;
+		else
+			right->srcfile = get_srcfile(right);
+	}
+	return strcmp(right->srcfile, left->srcfile);
+}
+
+static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
+					size_t size, unsigned int width)
+{
+	return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
+}
+
+struct sort_entry sort_srcfile = {
+	.se_header	= "Source File",
+	.se_cmp		= sort__srcfile_cmp,
+	.se_snprintf	= hist_entry__srcfile_snprintf,
+	.se_width_idx	= HISTC_SRCFILE,
+};
+
 /* --sort parent */
 
 static int64_t
@@ -1196,6 +1247,7 @@ struct sort_dimension {
 	DIM(SORT_PARENT, "parent", sort_parent),
 	DIM(SORT_CPU, "cpu", sort_cpu),
 	DIM(SORT_SRCLINE, "srcline", sort_srcline),
+	DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
 	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
 	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
 	DIM(SORT_TRANSACTION, "transaction", sort_transaction),
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index bc6c87a..3c2a399 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -114,6 +114,7 @@ struct hist_entry {
 		};
 	};
 	char			*srcline;
+	char			*srcfile;
 	struct symbol		*parent;
 	struct rb_root		sorted_chain;
 	struct branch_info	*branch_info;
@@ -172,6 +173,7 @@ enum sort_type {
 	SORT_PARENT,
 	SORT_CPU,
 	SORT_SRCLINE,
+	SORT_SRCFILE,
 	SORT_LOCAL_WEIGHT,
 	SORT_GLOBAL_WEIGHT,
 	SORT_TRANSACTION,

The commit for this change in Linux stable tree is 31191a8 (patch).

Leave a Reply

Your email address will not be published. Required fields are marked *