public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Jiri Olsa <jolsa@redhat.com>, LKML <linux-kernel@vger.kernel.org>,
	David Ahern <dsahern@gmail.com>,
	Stephane Eranian <eranian@google.com>,
	Andi Kleen <andi@firstfloor.org>,
	Minchan Kim <minchan@kernel.org>
Subject: [RFC/PATCH] perf stat: Show sample events stat for a data file
Date: Wed, 29 Apr 2015 16:27:45 +0900	[thread overview]
Message-ID: <1430292465-8863-1-git-send-email-namhyung@kernel.org> (raw)

Add --input option to 'perf stat' so that it can show event stats of the
file.  I would like to use a short '-i' option to be compatible with
other commands but it was already taken by '--no-inherit' option, so it
only supports the long option.

The example output looks like below:

  $ perf record -a sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.635 MB perf.data (1946 samples) ]

  $ perf stat --input perf.data

    Total event stats for 'perf.data' file:

              TOTAL events:       6837
               MMAP events:        116
               COMM events:        375
               EXIT events:          2
           THROTTLE events:         12
         UNTHROTTLE events:         11
               FORK events:        374
             SAMPLE events:       1946
              MMAP2 events:       3999
     FINISHED_ROUND events:          2

   Sample event stats:

         361,255,234      cycles
               1,946      samples                   #   sampling ratio  12.162% (486/4000)

         0.998581085 second time sampled

The sampling ratio was useful for me to determine how often the event
was sampled - in this case the cpu cycles event was only sampled at 12%
of the expected sampling frequency, so the system was mostly idle in
terms of cpu cycles (or the event was multiplexed in case of recording
large number of events at once).

The sampling ratio was calulated like below:

  expected_freq  = evsel->attr.sample_freq
  actual_freq    = (nr_samples / nr_cpus) / sample_time
  sampling_ratio = 100 * actual_freq / expected_freq

Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-stat.c | 91 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index fd577f725d23..78ded82df4a9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -58,6 +58,7 @@
 #include "util/cpumap.h"
 #include "util/thread.h"
 #include "util/thread_map.h"
+#include "util/hist.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -1576,6 +1577,87 @@ static int perf_stat_init_aggr_mode(void)
 	return 0;
 }
 
+static u64 first_sample_nsec;
+static u64 last_sample_nsec;
+
+static int process_sample_event(struct perf_tool *tool __maybe_unused,
+				union perf_event *event __maybe_unused,
+				struct perf_sample *sample,
+				struct perf_evsel *evsel,
+				struct machine *machine __maybe_unused)
+{
+	struct hists *hists = evsel__hists(evsel);
+
+	if (!first_sample_nsec)
+		first_sample_nsec = sample->time;
+	last_sample_nsec = sample->time;
+
+	hists->stats.total_period += sample->period;
+	hists->stats.nr_events[PERF_RECORD_SAMPLE]++;
+	return 0;
+}
+
+static int show_sample_stat(void)
+{
+	struct perf_data_file file = {
+		.mode  = PERF_DATA_MODE_READ,
+		.path  = input_name,
+	};
+	struct perf_tool tool = {
+		.sample = process_sample_event,
+	};
+	struct perf_session *session;
+	struct perf_evsel *evsel;
+	u64 sample_nsec;
+	int nr_cpus;
+	int ret;
+
+	session = perf_session__new(&file, false, &tool);
+	if (session == NULL)
+		return -1;
+
+	ret = perf_session__process_events(session);
+	if (ret < 0)
+		return ret;
+
+	nr_cpus = session->header.env.nr_cpus_online;
+	sample_nsec = last_sample_nsec - first_sample_nsec;
+
+	fprintf(output, "\n Total event stats for '%s' file:\n\n", input_name);
+	events_stats__fprintf(&session->evlist->stats, output);
+
+	fprintf(output, "\n Sample event stats:\n\n");
+	evlist__for_each(session->evlist, evsel) {
+		struct hists *hists = evsel__hists(evsel);
+		struct events_stats *stats = &hists->stats;
+		u64 total_period = stats->total_period;
+		u32 nr_samples = stats->nr_events[PERF_RECORD_SAMPLE];
+
+		fprintf(output, "%'18"PRIu64"      ", total_period);
+		fprintf(output, "%-25s", perf_evsel__name(evsel));
+		fprintf(output, "\n");
+		fprintf(output, "%'18u      ", nr_samples);
+		fprintf(output, "%-25s", "samples");
+
+		if (sample_nsec && evsel->attr.freq && evsel->attr.sample_freq) {
+			int expected_rate = evsel->attr.sample_freq;
+			double sample_rate = 1.0 * nr_samples / nr_cpus;
+
+			sample_rate *= (double)NSEC_PER_SEC / sample_nsec;
+			fprintf(output, " #   sampling ratio  %.3f%% (%d/%d)",
+				100 * sample_rate / expected_rate,
+				(int)sample_rate, expected_rate);
+		}
+		fprintf(output, "\n\n");
+	}
+
+	fprintf(output, "%18.9f second time sampled\n",
+		(double)sample_nsec / NSEC_PER_SEC);
+
+	perf_session__delete(session);
+	return 0;
+}
+
 static int setup_events(const char * const *attrs, unsigned len)
 {
 	unsigned i;
@@ -1793,6 +1875,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		   "print counts with custom separator"),
 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
 		     "monitor event in cgroup name only", parse_cgroups),
+	OPT_STRING(0, "input", &input_name, "file", "input file name"),
 	OPT_STRING('o', "output", &output_name, "file", "output file name"),
 	OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
 	OPT_INTEGER(0, "log-fd", &output_fd,
@@ -1886,8 +1969,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	} else if (big_num_opt == 0) /* User passed --no-big-num */
 		big_num = false;
 
-	if (!argc && target__none(&target))
-		usage_with_options(stat_usage, options);
+	if (!argc && target__none(&target)) {
+		if (!input_name)
+			usage_with_options(stat_usage, options);
+		status = show_sample_stat();
+		goto out;
+	}
 
 	if (run_count < 0) {
 		pr_err("Run count must be a positive number\n");
-- 
2.3.5


             reply	other threads:[~2015-04-29  7:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-29  7:27 Namhyung Kim [this message]
2015-04-29  7:42 ` [RFC/PATCH] perf stat: Show sample events stat for a data file Jiri Olsa
2015-04-29  7:58   ` Namhyung Kim
2015-04-29  9:27 ` Peter Zijlstra
2015-04-29 11:58   ` Namhyung Kim
2015-05-08 14:46     ` Peter Zijlstra
2015-05-09 14:39       ` Namhyung Kim

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=1430292465-8863-1-git-send-email-namhyung@kernel.org \
    --to=namhyung@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=andi@firstfloor.org \
    --cc=dsahern@gmail.com \
    --cc=eranian@google.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=minchan@kernel.org \
    --cc=mingo@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox