All of lore.kernel.org
 help / color / mirror / Atom feed
From: kan.liang@intel.com
To: acme@kernel.org, jolsa@kernel.org
Cc: namhyung@kernel.org, ak@linux.intel.com,
	linux-kernel@vger.kernel.org, Kan Liang <kan.liang@intel.com>
Subject: [PATCH RFC V3 4/5] perf,tool: partial callgrap support
Date: Wed,  8 Jul 2015 04:44:56 -0400	[thread overview]
Message-ID: <1436345097-11113-5-git-send-email-kan.liang@intel.com> (raw)
In-Reply-To: <1436345097-11113-1-git-send-email-kan.liang@intel.com>

From: Kan Liang <kan.liang@intel.com>

When multiple events are sampled it may not be needed to collect
callgraphs for all of them. The sample sites are usually nearby, and
it's enough to collect the callgraphs on a reference event (such as
precise cycles or precise instructions).
This patchkit adds the ability to turn off callgraphs and time stamps
per event. This in term can reduce sampling overhead and the size of the
perf.data. Furthermore, it makes collecting back traces and timestamps
possible when PEBS threshold > 1, which significantly reducing the
sampling overhead especially for frequently occurring events
(https://lkml.org/lkml/2015/5/10/196). For example, A slower event with
a larger period collects back traces/timestamps. Other more events run
fast with multi-pebs. The time stamps from the slower events can be used
to order the faster events. Their backtraces can give the user enough
hint to find the right spot.

Here are some examples and test results.

1. Comparing the elapsed time and perf.data size from "kernbench -M -H".

 The test command for FULL callgrap and time support.
   "perf record -e
   '{cpu/cpu-cycles,period=100000/,cpu/instructions,period=20000/p}'
   --call-graph fp --time"

 The test command for PARTIAL callgrap and time support.
   "perf record -e
   '{cpu/cpu-cycles,callgraph=fp,time,period=100000/,
     cpu/instructions,callgraph=no,time=0,period=20000/p}'"

 The elapsed time for FULL is 24.3 Sec, while for PARTIAL is 16.9 Sec.
 The perf.data size for FULL is 22.1 Gb, while for PARTIAL is 12.4 Gb.

2. Comparing the perf.data size and callgraph results.

 The test command for FULL callgrap and time support.
   "perf record -e
   '{cpu/cpu-cycles,period=100000/pp,cpu/instructions,period=20000/p}'
   --call-graph fp -- ./tchain_edit"

 The test command for PARTIAL callgrap and time support.
   "perf record -e
   '{cpu/cpu-cycles,callgraph=fp,time,period=100000/pp,
     cpu/instructions,callgraph=no,time=0,period=20000/p}'
   -- ./tchain_edit"

 The perf.data size for FULL is 43.2 MB, while for PARTIAL is 21.1 MB.
 The callgraph is roughly the same.

 The callgraph from FULL
 # Samples: 87K of event
 'cpu/cpu-cycles,callgraph=fp,time,period=100000/pp'
 # Event count (approx.): 8760000000
 #
 # Children      Self  Command      Shared Object       Symbol
 # ........  ........  ...........  ..................
..........................................
 #
    99.98%     0.00%  tchain_edit  libc-2.15.so        [.]
__libc_start_main
            |
            ---__libc_start_main

    99.97%     0.00%  tchain_edit  tchain_edit         [.] main
            |
            ---main
               __libc_start_main

    99.97%     0.00%  tchain_edit  tchain_edit         [.] f1
            |
            ---f1
               main
               __libc_start_main

    99.85%    87.01%  tchain_edit  tchain_edit         [.] f3
            |
            ---f3
               |
               |--99.74%-- f2
               |          f1
               |          main
               |          __libc_start_main
                --0.26%-- [...]
    99.71%     0.12%  tchain_edit  tchain_edit         [.] f2
            |
            ---f2
               f1
               main
               __libc_start_main

 The callgraph from PARTIAL
 # Samples: 417K of event
 'cpu/instructions,callgraph=no,time=0,period=20000/p'
 # Event count (approx.): 8346980000
 #
 # Children      Self  Command      Shared Object     Symbol
 # ........  ........  ...........  ................
..........................................
 #
    98.82%     0.00%  tchain_edit  libc-2.15.so      [.]
__libc_start_main
            |
            ---__libc_start_main

    98.82%     0.00%  tchain_edit  tchain_edit       [.] main
            |
            ---main
               __libc_start_main

    98.82%     0.00%  tchain_edit  tchain_edit       [.] f1
            |
            ---f1
               main
               __libc_start_main

    98.82%    98.28%  tchain_edit  tchain_edit       [.] f3
            |
            ---f3
               |
               |--0.53%-- f2
               |          f1
               |          main
               |          __libc_start_main
               |
               |--0.01%-- f1
               |          main
               |          __libc_start_main
                --99.46%-- [...]
    97.63%     0.03%  tchain_edit  tchain_edit       [.] f2
            |
            ---f2
               f1
               main
               __libc_start_main

     7.13%     0.03%  tchain_edit  [kernel.vmlinux]  [k] do_nmi
            |
            ---do_nmi
               end_repeat_nmi
               f3
               f2
               f1
               main
               __libc_start_main

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/Documentation/perf-record.txt |  4 ++++
 tools/perf/util/evsel.c                  | 24 +++++++++++++++++++++++-
 tools/perf/util/parse-events.c           | 18 ++++++++++++++++++
 tools/perf/util/parse-events.h           |  2 ++
 tools/perf/util/parse-events.l           |  2 ++
 5 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index df47907..f478dc2 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -52,6 +52,10 @@ OPTIONS
 	  - 'time': Disable/enable time stamping. Acceptable values are 1 for
 		    enabling time stamping. 0 for disabling time stamping.
 		    The default is 1.
+	  - 'callgraph': Disable/enable callgraph. Acceptable str are "fp" for
+			 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and
+			 "no" for disable callgraph.
+	  - 'stack_size': user stack size for dwarf mode
 	  Note: If user explicitly sets options which conflict with the params,
 	  the value set by the params will be overridden.
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1d58330..f6b0a2d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -620,6 +620,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 	int track = evsel->tracking;
 	bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
 	bool sample_time = opts->sample_time;
+	bool callgraph = callchain_param.enabled;
 
 	attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
 	attr->inherit	    = !opts->no_inherit;
@@ -636,6 +637,23 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 			sample_time = false;
 	}
 
+	if (!opts->callgraph_set) {
+		if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
+			callgraph = true;
+			if (attr->sample_type & PERF_SAMPLE_STACK_USER) {
+				callchain_param.record_mode = CALLCHAIN_DWARF;
+				if (attr->sample_stack_user)
+					callchain_param.dump_size = attr->sample_stack_user;
+				else
+					callchain_param.dump_size = 8192;
+			} else if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK)
+				callchain_param.record_mode = CALLCHAIN_LBR;
+			else
+				callchain_param.record_mode = CALLCHAIN_FP;
+		} else
+			callgraph = false;
+	}
+
 	/*
 	 * Event parsing doesn't check the availability
 	 * Clear the bit which event parsing may be set.
@@ -650,6 +668,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 		evsel->sample_size -= sizeof(u64);
 	}
 
+	attr->sample_type &= ~(PERF_SAMPLE_CALLCHAIN |
+			       PERF_SAMPLE_STACK_USER |
+			       PERF_SAMPLE_BRANCH_STACK);
+
 	perf_evsel__set_sample_bit(evsel, IP);
 	perf_evsel__set_sample_bit(evsel, TID);
 
@@ -715,7 +737,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 	if (perf_evsel__is_function_event(evsel))
 		evsel->attr.exclude_callchain_user = 1;
 
-	if (callchain_param.enabled && !evsel->no_aux_samples)
+	if (callgraph && !evsel->no_aux_samples)
 		perf_evsel__config_callgraph(evsel, opts);
 
 	if (opts->sample_intr_regs) {
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9510047..14b5e56 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -19,6 +19,7 @@
 #include "thread_map.h"
 #include "cpumap.h"
 #include "asm/bug.h"
+#include "callchain.h"
 
 #define MAX_NAME_LEN 100
 
@@ -605,6 +606,23 @@ do {									   \
 		if (term->val.num == 1)
 			attr->sample_type |= PERF_SAMPLE_TIME;
 		 break;
+	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
+		CHECK_TYPE_VAL(STR);
+		if (!strcmp(term->val.str, "fp"))
+			attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
+		else if (!strcmp(term->val.str, "dwarf"))
+			attr->sample_type |= PERF_SAMPLE_CALLCHAIN |
+					     PERF_SAMPLE_STACK_USER;
+		else if (!strcmp(term->val.str, "lbr"))
+			attr->sample_type |= PERF_SAMPLE_CALLCHAIN |
+					     PERF_SAMPLE_BRANCH_STACK;
+		else if (strcmp(term->val.str, "no"))
+			return -EINVAL;
+		break;
+	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
+		CHECK_TYPE_VAL(NUM);
+		attr->sample_stack_user = term->val.num;
+		break;
 	case PARSE_EVENTS__TERM_TYPE_NAME:
 		CHECK_TYPE_VAL(STR);
 		break;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 0d8cae3..63fb763 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -63,6 +63,8 @@ enum {
 	PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
 	PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
 	PARSE_EVENTS__TERM_TYPE_TIME,
+	PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
+	PARSE_EVENTS__TERM_TYPE_STACKSIZE,
 };
 
 struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index f542750..16af73b 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -184,6 +184,8 @@ name			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
 period			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
 branch_type		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
 time			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
+callgraph		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
+stack_size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
 ,			{ return ','; }
 "/"			{ BEGIN(INITIAL); return '/'; }
 {name_minus}		{ return str(yyscanner, PE_NAME); }
-- 
1.8.3.1


  parent reply	other threads:[~2015-07-08 15:59 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-08  8:44 [PATCH RFC V3 0/5] partial callgrap and time support kan.liang
2015-07-08  8:44 ` [PATCH RFC V3 1/5] perf,tools: introduce OPT_CALLBACK_SET/OPT_CALLBACK_NOOPT_SET kan.liang
2015-07-14  6:54   ` Jiri Olsa
2015-07-08  8:44 ` [PATCH RFC V3 2/5] perf/documentation: Add description for period kan.liang
2015-07-14  6:55   ` Jiri Olsa
2015-07-14 14:05     ` Arnaldo Carvalho de Melo
2015-07-21  9:31   ` [tip:perf/core] perf record: Document setting '-e pmu/period=N/' in man page tip-bot for Kan Liang
2015-07-08  8:44 ` [PATCH RFC V3 3/5] perf,tool: partial time support kan.liang
2015-07-13 13:27   ` Namhyung Kim
2015-07-13 19:01     ` Liang, Kan
2015-07-14  1:04       ` Namhyung Kim
2015-07-15 19:03         ` Liang, Kan
2015-07-17  7:12           ` Namhyung Kim
2015-07-14  6:54   ` Jiri Olsa
2015-07-14  6:54   ` Jiri Olsa
2015-07-08  8:44 ` kan.liang [this message]
2015-07-08  8:44 ` [PATCH RFC V3 5/5] perf,tests: Add tests to callgrap and time parse kan.liang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1436345097-11113-5-git-send-email-kan.liang@intel.com \
    --to=kan.liang@intel.com \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.