xref: /openbmc/linux/tools/perf/builtin-stat.c (revision 9cffa8d5)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-stat.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin stat command: Give a precise performance counters summary
586470930SIngo Molnar  * overview about any workload, CPU or specific PID.
686470930SIngo Molnar  *
786470930SIngo Molnar  * Sample output:
886470930SIngo Molnar 
986470930SIngo Molnar    $ perf stat ~/hackbench 10
1086470930SIngo Molnar    Time: 0.104
1186470930SIngo Molnar 
1286470930SIngo Molnar     Performance counter stats for '/home/mingo/hackbench':
1386470930SIngo Molnar 
1486470930SIngo Molnar        1255.538611  task clock ticks     #      10.143 CPU utilization factor
1586470930SIngo Molnar              54011  context switches     #       0.043 M/sec
1686470930SIngo Molnar                385  CPU migrations       #       0.000 M/sec
1786470930SIngo Molnar              17755  pagefaults           #       0.014 M/sec
1886470930SIngo Molnar         3808323185  CPU cycles           #    3033.219 M/sec
1986470930SIngo Molnar         1575111190  instructions         #    1254.530 M/sec
2086470930SIngo Molnar           17367895  cache references     #      13.833 M/sec
2186470930SIngo Molnar            7674421  cache misses         #       6.112 M/sec
2286470930SIngo Molnar 
2386470930SIngo Molnar     Wall-clock time elapsed:   123.786620 msecs
2486470930SIngo Molnar 
2586470930SIngo Molnar  *
2686470930SIngo Molnar  * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
2786470930SIngo Molnar  *
2886470930SIngo Molnar  * Improvements and fixes by:
2986470930SIngo Molnar  *
3086470930SIngo Molnar  *   Arjan van de Ven <arjan@linux.intel.com>
3186470930SIngo Molnar  *   Yanmin Zhang <yanmin.zhang@intel.com>
3286470930SIngo Molnar  *   Wu Fengguang <fengguang.wu@intel.com>
3386470930SIngo Molnar  *   Mike Galbraith <efault@gmx.de>
3486470930SIngo Molnar  *   Paul Mackerras <paulus@samba.org>
3586470930SIngo Molnar  *
3686470930SIngo Molnar  * Released under the GPL v2. (and only v2, not any later version)
3786470930SIngo Molnar  */
3886470930SIngo Molnar 
3986470930SIngo Molnar #include "perf.h"
4086470930SIngo Molnar #include "builtin.h"
4186470930SIngo Molnar #include "util/util.h"
4286470930SIngo Molnar #include "util/parse-options.h"
4386470930SIngo Molnar #include "util/parse-events.h"
4486470930SIngo Molnar 
4586470930SIngo Molnar #include <sys/prctl.h>
4642202dd5SIngo Molnar #include <math.h>
4786470930SIngo Molnar 
4886470930SIngo Molnar static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
4986470930SIngo Molnar 
50f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK	},
51f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
52f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS	},
53f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS	},
5486470930SIngo Molnar 
55f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES	},
56f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS	},
57f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES},
58f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES	},
59f4dbfa8fSPeter Zijlstra 
6086470930SIngo Molnar };
6186470930SIngo Molnar 
6286470930SIngo Molnar static int			system_wide			=  0;
6386470930SIngo Molnar static int			inherit				=  1;
64743ee1f8SIngo Molnar static int			verbose				=  0;
6586470930SIngo Molnar 
6686470930SIngo Molnar static int			fd[MAX_NR_CPUS][MAX_COUNTERS];
6786470930SIngo Molnar 
6886470930SIngo Molnar static int			target_pid			= -1;
6986470930SIngo Molnar static int			nr_cpus				=  0;
7086470930SIngo Molnar static unsigned int		page_size;
7186470930SIngo Molnar 
7286470930SIngo Molnar static int			scale				=  1;
7386470930SIngo Molnar 
7486470930SIngo Molnar static const unsigned int default_count[] = {
7586470930SIngo Molnar 	1000000,
7686470930SIngo Molnar 	1000000,
7786470930SIngo Molnar 	  10000,
7886470930SIngo Molnar 	  10000,
7986470930SIngo Molnar 	1000000,
8086470930SIngo Molnar 	  10000,
8186470930SIngo Molnar };
8286470930SIngo Molnar 
8342202dd5SIngo Molnar #define MAX_RUN 100
8486470930SIngo Molnar 
8542202dd5SIngo Molnar static int			run_count		=  1;
8642202dd5SIngo Molnar static int			run_idx			=  0;
8742202dd5SIngo Molnar 
889cffa8d5SPaul Mackerras static u64			event_res[MAX_RUN][MAX_COUNTERS][3];
899cffa8d5SPaul Mackerras static u64			event_scaled[MAX_RUN][MAX_COUNTERS];
9042202dd5SIngo Molnar 
919cffa8d5SPaul Mackerras //static u64			event_hist[MAX_RUN][MAX_COUNTERS][3];
9242202dd5SIngo Molnar 
9342202dd5SIngo Molnar 
949cffa8d5SPaul Mackerras static u64			runtime_nsecs[MAX_RUN];
959cffa8d5SPaul Mackerras static u64			walltime_nsecs[MAX_RUN];
969cffa8d5SPaul Mackerras static u64			runtime_cycles[MAX_RUN];
9742202dd5SIngo Molnar 
989cffa8d5SPaul Mackerras static u64			event_res_avg[MAX_COUNTERS][3];
999cffa8d5SPaul Mackerras static u64			event_res_noise[MAX_COUNTERS][3];
10042202dd5SIngo Molnar 
1019cffa8d5SPaul Mackerras static u64			event_scaled_avg[MAX_COUNTERS];
10242202dd5SIngo Molnar 
1039cffa8d5SPaul Mackerras static u64			runtime_nsecs_avg;
1049cffa8d5SPaul Mackerras static u64			runtime_nsecs_noise;
10542202dd5SIngo Molnar 
1069cffa8d5SPaul Mackerras static u64			walltime_nsecs_avg;
1079cffa8d5SPaul Mackerras static u64			walltime_nsecs_noise;
10842202dd5SIngo Molnar 
1099cffa8d5SPaul Mackerras static u64			runtime_cycles_avg;
1109cffa8d5SPaul Mackerras static u64			runtime_cycles_noise;
11186470930SIngo Molnar 
112743ee1f8SIngo Molnar static void create_perf_stat_counter(int counter)
11386470930SIngo Molnar {
11486470930SIngo Molnar 	struct perf_counter_attr *attr = attrs + counter;
11586470930SIngo Molnar 
11686470930SIngo Molnar 	if (scale)
11786470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
11886470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
11986470930SIngo Molnar 
12086470930SIngo Molnar 	if (system_wide) {
12186470930SIngo Molnar 		int cpu;
12286470930SIngo Molnar 		for (cpu = 0; cpu < nr_cpus; cpu ++) {
12386470930SIngo Molnar 			fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
124743ee1f8SIngo Molnar 			if (fd[cpu][counter] < 0 && verbose) {
125743ee1f8SIngo Molnar 				printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno));
12686470930SIngo Molnar 			}
12786470930SIngo Molnar 		}
12886470930SIngo Molnar 	} else {
12986470930SIngo Molnar 		attr->inherit	= inherit;
13086470930SIngo Molnar 		attr->disabled	= 1;
13186470930SIngo Molnar 
13286470930SIngo Molnar 		fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0);
133743ee1f8SIngo Molnar 		if (fd[0][counter] < 0 && verbose) {
134743ee1f8SIngo Molnar 			printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno));
13586470930SIngo Molnar 		}
13686470930SIngo Molnar 	}
13786470930SIngo Molnar }
13886470930SIngo Molnar 
13986470930SIngo Molnar /*
14086470930SIngo Molnar  * Does the counter have nsecs as a unit?
14186470930SIngo Molnar  */
14286470930SIngo Molnar static inline int nsec_counter(int counter)
14386470930SIngo Molnar {
14486470930SIngo Molnar 	if (attrs[counter].type != PERF_TYPE_SOFTWARE)
14586470930SIngo Molnar 		return 0;
14686470930SIngo Molnar 
147f4dbfa8fSPeter Zijlstra 	if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
14886470930SIngo Molnar 		return 1;
14986470930SIngo Molnar 
150f4dbfa8fSPeter Zijlstra 	if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
15186470930SIngo Molnar 		return 1;
15286470930SIngo Molnar 
15386470930SIngo Molnar 	return 0;
15486470930SIngo Molnar }
15586470930SIngo Molnar 
15686470930SIngo Molnar /*
15786470930SIngo Molnar  * Read out the results of a single counter:
15886470930SIngo Molnar  */
15986470930SIngo Molnar static void read_counter(int counter)
16086470930SIngo Molnar {
1619cffa8d5SPaul Mackerras 	u64 *count, single_count[3];
16286470930SIngo Molnar 	ssize_t res;
16386470930SIngo Molnar 	int cpu, nv;
16486470930SIngo Molnar 	int scaled;
16586470930SIngo Molnar 
16642202dd5SIngo Molnar 	count = event_res[run_idx][counter];
16786470930SIngo Molnar 
16886470930SIngo Molnar 	count[0] = count[1] = count[2] = 0;
16986470930SIngo Molnar 
17086470930SIngo Molnar 	nv = scale ? 3 : 1;
17186470930SIngo Molnar 	for (cpu = 0; cpu < nr_cpus; cpu ++) {
172743ee1f8SIngo Molnar 		if (fd[cpu][counter] < 0)
173743ee1f8SIngo Molnar 			continue;
174743ee1f8SIngo Molnar 
1759cffa8d5SPaul Mackerras 		res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
1769cffa8d5SPaul Mackerras 		assert(res == nv * sizeof(u64));
17742202dd5SIngo Molnar 		close(fd[cpu][counter]);
17842202dd5SIngo Molnar 		fd[cpu][counter] = -1;
17986470930SIngo Molnar 
18086470930SIngo Molnar 		count[0] += single_count[0];
18186470930SIngo Molnar 		if (scale) {
18286470930SIngo Molnar 			count[1] += single_count[1];
18386470930SIngo Molnar 			count[2] += single_count[2];
18486470930SIngo Molnar 		}
18586470930SIngo Molnar 	}
18686470930SIngo Molnar 
18786470930SIngo Molnar 	scaled = 0;
18886470930SIngo Molnar 	if (scale) {
18986470930SIngo Molnar 		if (count[2] == 0) {
19042202dd5SIngo Molnar 			event_scaled[run_idx][counter] = -1;
19186470930SIngo Molnar 			count[0] = 0;
19286470930SIngo Molnar 			return;
19386470930SIngo Molnar 		}
19486470930SIngo Molnar 
19586470930SIngo Molnar 		if (count[2] < count[1]) {
19642202dd5SIngo Molnar 			event_scaled[run_idx][counter] = 1;
19786470930SIngo Molnar 			count[0] = (unsigned long long)
19886470930SIngo Molnar 				((double)count[0] * count[1] / count[2] + 0.5);
19986470930SIngo Molnar 		}
20086470930SIngo Molnar 	}
20186470930SIngo Molnar 	/*
20286470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
20386470930SIngo Molnar 	 */
20486470930SIngo Molnar 	if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
205f4dbfa8fSPeter Zijlstra 		attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
20642202dd5SIngo Molnar 		runtime_nsecs[run_idx] = count[0];
207e779898aSIngo Molnar 	if (attrs[counter].type == PERF_TYPE_HARDWARE &&
208f4dbfa8fSPeter Zijlstra 		attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
20942202dd5SIngo Molnar 		runtime_cycles[run_idx] = count[0];
21086470930SIngo Molnar }
21186470930SIngo Molnar 
21242202dd5SIngo Molnar static int run_perf_stat(int argc, const char **argv)
21386470930SIngo Molnar {
21486470930SIngo Molnar 	unsigned long long t0, t1;
21542202dd5SIngo Molnar 	int status = 0;
21686470930SIngo Molnar 	int counter;
21786470930SIngo Molnar 	int pid;
21886470930SIngo Molnar 
21986470930SIngo Molnar 	if (!system_wide)
22086470930SIngo Molnar 		nr_cpus = 1;
22186470930SIngo Molnar 
22286470930SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
223743ee1f8SIngo Molnar 		create_perf_stat_counter(counter);
22486470930SIngo Molnar 
22586470930SIngo Molnar 	/*
22686470930SIngo Molnar 	 * Enable counters and exec the command:
22786470930SIngo Molnar 	 */
22886470930SIngo Molnar 	t0 = rdclock();
22986470930SIngo Molnar 	prctl(PR_TASK_PERF_COUNTERS_ENABLE);
23086470930SIngo Molnar 
23186470930SIngo Molnar 	if ((pid = fork()) < 0)
23286470930SIngo Molnar 		perror("failed to fork");
23386470930SIngo Molnar 
23486470930SIngo Molnar 	if (!pid) {
23586470930SIngo Molnar 		if (execvp(argv[0], (char **)argv)) {
23686470930SIngo Molnar 			perror(argv[0]);
23786470930SIngo Molnar 			exit(-1);
23886470930SIngo Molnar 		}
23986470930SIngo Molnar 	}
24086470930SIngo Molnar 
24142202dd5SIngo Molnar 	wait(&status);
24286470930SIngo Molnar 
24386470930SIngo Molnar 	prctl(PR_TASK_PERF_COUNTERS_DISABLE);
24486470930SIngo Molnar 	t1 = rdclock();
24586470930SIngo Molnar 
24642202dd5SIngo Molnar 	walltime_nsecs[run_idx] = t1 - t0;
24742202dd5SIngo Molnar 
24842202dd5SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
24942202dd5SIngo Molnar 		read_counter(counter);
25042202dd5SIngo Molnar 
25142202dd5SIngo Molnar 	return WEXITSTATUS(status);
25242202dd5SIngo Molnar }
25342202dd5SIngo Molnar 
2549cffa8d5SPaul Mackerras static void print_noise(u64 *count, u64 *noise)
25542202dd5SIngo Molnar {
25642202dd5SIngo Molnar 	if (run_count > 1)
25742202dd5SIngo Molnar 		fprintf(stderr, "   ( +- %7.3f%% )",
25842202dd5SIngo Molnar 			(double)noise[0]/(count[0]+1)*100.0);
25942202dd5SIngo Molnar }
26042202dd5SIngo Molnar 
2619cffa8d5SPaul Mackerras static void nsec_printout(int counter, u64 *count, u64 *noise)
26242202dd5SIngo Molnar {
26342202dd5SIngo Molnar 	double msecs = (double)count[0] / 1000000;
26442202dd5SIngo Molnar 
26542202dd5SIngo Molnar 	fprintf(stderr, " %14.6f  %-20s", msecs, event_name(counter));
26642202dd5SIngo Molnar 
26742202dd5SIngo Molnar 	if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
26842202dd5SIngo Molnar 		attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
26942202dd5SIngo Molnar 
27042202dd5SIngo Molnar 		if (walltime_nsecs_avg)
27142202dd5SIngo Molnar 			fprintf(stderr, " # %10.3f CPUs ",
27242202dd5SIngo Molnar 				(double)count[0] / (double)walltime_nsecs_avg);
27342202dd5SIngo Molnar 	}
27442202dd5SIngo Molnar 	print_noise(count, noise);
27542202dd5SIngo Molnar }
27642202dd5SIngo Molnar 
2779cffa8d5SPaul Mackerras static void abs_printout(int counter, u64 *count, u64 *noise)
27842202dd5SIngo Molnar {
27942202dd5SIngo Molnar 	fprintf(stderr, " %14Ld  %-20s", count[0], event_name(counter));
28042202dd5SIngo Molnar 
28142202dd5SIngo Molnar 	if (runtime_cycles_avg &&
28242202dd5SIngo Molnar 		attrs[counter].type == PERF_TYPE_HARDWARE &&
28342202dd5SIngo Molnar 			attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
28442202dd5SIngo Molnar 
28542202dd5SIngo Molnar 		fprintf(stderr, " # %10.3f IPC  ",
28642202dd5SIngo Molnar 			(double)count[0] / (double)runtime_cycles_avg);
28742202dd5SIngo Molnar 	} else {
28842202dd5SIngo Molnar 		if (runtime_nsecs_avg) {
28942202dd5SIngo Molnar 			fprintf(stderr, " # %10.3f M/sec",
29042202dd5SIngo Molnar 				(double)count[0]/runtime_nsecs_avg*1000.0);
29142202dd5SIngo Molnar 		}
29242202dd5SIngo Molnar 	}
29342202dd5SIngo Molnar 	print_noise(count, noise);
29442202dd5SIngo Molnar }
29542202dd5SIngo Molnar 
29642202dd5SIngo Molnar /*
29742202dd5SIngo Molnar  * Print out the results of a single counter:
29842202dd5SIngo Molnar  */
29942202dd5SIngo Molnar static void print_counter(int counter)
30042202dd5SIngo Molnar {
3019cffa8d5SPaul Mackerras 	u64 *count, *noise;
30242202dd5SIngo Molnar 	int scaled;
30342202dd5SIngo Molnar 
30442202dd5SIngo Molnar 	count = event_res_avg[counter];
30542202dd5SIngo Molnar 	noise = event_res_noise[counter];
30642202dd5SIngo Molnar 	scaled = event_scaled_avg[counter];
30742202dd5SIngo Molnar 
30842202dd5SIngo Molnar 	if (scaled == -1) {
30942202dd5SIngo Molnar 		fprintf(stderr, " %14s  %-20s\n",
31042202dd5SIngo Molnar 			"<not counted>", event_name(counter));
31142202dd5SIngo Molnar 		return;
31242202dd5SIngo Molnar 	}
31342202dd5SIngo Molnar 
31442202dd5SIngo Molnar 	if (nsec_counter(counter))
31542202dd5SIngo Molnar 		nsec_printout(counter, count, noise);
31642202dd5SIngo Molnar 	else
31742202dd5SIngo Molnar 		abs_printout(counter, count, noise);
31842202dd5SIngo Molnar 
31942202dd5SIngo Molnar 	if (scaled)
32042202dd5SIngo Molnar 		fprintf(stderr, "  (scaled from %.2f%%)",
32142202dd5SIngo Molnar 			(double) count[2] / count[1] * 100);
32242202dd5SIngo Molnar 
32342202dd5SIngo Molnar 	fprintf(stderr, "\n");
32442202dd5SIngo Molnar }
32542202dd5SIngo Molnar 
32642202dd5SIngo Molnar /*
327ef281a19SIngo Molnar  * normalize_noise noise values down to stddev:
32842202dd5SIngo Molnar  */
3299cffa8d5SPaul Mackerras static void normalize_noise(u64 *val)
33042202dd5SIngo Molnar {
33142202dd5SIngo Molnar 	double res;
33242202dd5SIngo Molnar 
33342202dd5SIngo Molnar 	res = (double)*val / (run_count * sqrt((double)run_count));
33442202dd5SIngo Molnar 
3359cffa8d5SPaul Mackerras 	*val = (u64)res;
33642202dd5SIngo Molnar }
33742202dd5SIngo Molnar 
3389cffa8d5SPaul Mackerras static void update_avg(const char *name, int idx, u64 *avg, u64 *val)
339ef281a19SIngo Molnar {
340ef281a19SIngo Molnar 	*avg += *val;
341ef281a19SIngo Molnar 
342ef281a19SIngo Molnar 	if (verbose > 1)
343ef281a19SIngo Molnar 		fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val);
344ef281a19SIngo Molnar }
34542202dd5SIngo Molnar /*
34642202dd5SIngo Molnar  * Calculate the averages and noises:
34742202dd5SIngo Molnar  */
34842202dd5SIngo Molnar static void calc_avg(void)
34942202dd5SIngo Molnar {
35042202dd5SIngo Molnar 	int i, j;
35142202dd5SIngo Molnar 
352ef281a19SIngo Molnar 	if (verbose > 1)
353ef281a19SIngo Molnar 		fprintf(stderr, "\n");
354ef281a19SIngo Molnar 
35542202dd5SIngo Molnar 	for (i = 0; i < run_count; i++) {
356ef281a19SIngo Molnar 		update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i);
357ef281a19SIngo Molnar 		update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i);
358ef281a19SIngo Molnar 		update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i);
35942202dd5SIngo Molnar 
36042202dd5SIngo Molnar 		for (j = 0; j < nr_counters; j++) {
361ef281a19SIngo Molnar 			update_avg("counter/0", j,
362ef281a19SIngo Molnar 				event_res_avg[j]+0, event_res[i][j]+0);
363ef281a19SIngo Molnar 			update_avg("counter/1", j,
364ef281a19SIngo Molnar 				event_res_avg[j]+1, event_res[i][j]+1);
365ef281a19SIngo Molnar 			update_avg("counter/2", j,
366ef281a19SIngo Molnar 				event_res_avg[j]+2, event_res[i][j]+2);
367ef281a19SIngo Molnar 			update_avg("scaled", j,
368ef281a19SIngo Molnar 				event_scaled_avg + j, event_scaled[i]+j);
36942202dd5SIngo Molnar 		}
37042202dd5SIngo Molnar 	}
37142202dd5SIngo Molnar 	runtime_nsecs_avg /= run_count;
37242202dd5SIngo Molnar 	walltime_nsecs_avg /= run_count;
37342202dd5SIngo Molnar 	runtime_cycles_avg /= run_count;
37442202dd5SIngo Molnar 
37542202dd5SIngo Molnar 	for (j = 0; j < nr_counters; j++) {
37642202dd5SIngo Molnar 		event_res_avg[j][0] /= run_count;
37742202dd5SIngo Molnar 		event_res_avg[j][1] /= run_count;
37842202dd5SIngo Molnar 		event_res_avg[j][2] /= run_count;
37942202dd5SIngo Molnar 	}
38042202dd5SIngo Molnar 
38142202dd5SIngo Molnar 	for (i = 0; i < run_count; i++) {
38242202dd5SIngo Molnar 		runtime_nsecs_noise +=
3839cffa8d5SPaul Mackerras 			abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg));
38442202dd5SIngo Molnar 		walltime_nsecs_noise +=
3859cffa8d5SPaul Mackerras 			abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg));
38642202dd5SIngo Molnar 		runtime_cycles_noise +=
3879cffa8d5SPaul Mackerras 			abs((s64)(runtime_cycles[i] - runtime_cycles_avg));
38842202dd5SIngo Molnar 
38942202dd5SIngo Molnar 		for (j = 0; j < nr_counters; j++) {
39042202dd5SIngo Molnar 			event_res_noise[j][0] +=
3919cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][0] - event_res_avg[j][0]));
39242202dd5SIngo Molnar 			event_res_noise[j][1] +=
3939cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][1] - event_res_avg[j][1]));
39442202dd5SIngo Molnar 			event_res_noise[j][2] +=
3959cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][2] - event_res_avg[j][2]));
39642202dd5SIngo Molnar 		}
39742202dd5SIngo Molnar 	}
39842202dd5SIngo Molnar 
399ef281a19SIngo Molnar 	normalize_noise(&runtime_nsecs_noise);
400ef281a19SIngo Molnar 	normalize_noise(&walltime_nsecs_noise);
401ef281a19SIngo Molnar 	normalize_noise(&runtime_cycles_noise);
40242202dd5SIngo Molnar 
40342202dd5SIngo Molnar 	for (j = 0; j < nr_counters; j++) {
404ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][0]);
405ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][1]);
406ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][2]);
40742202dd5SIngo Molnar 	}
40842202dd5SIngo Molnar }
40942202dd5SIngo Molnar 
41042202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
41142202dd5SIngo Molnar {
41242202dd5SIngo Molnar 	int i, counter;
41342202dd5SIngo Molnar 
41442202dd5SIngo Molnar 	calc_avg();
41542202dd5SIngo Molnar 
41686470930SIngo Molnar 	fflush(stdout);
41786470930SIngo Molnar 
41886470930SIngo Molnar 	fprintf(stderr, "\n");
41986470930SIngo Molnar 	fprintf(stderr, " Performance counter stats for \'%s", argv[0]);
42086470930SIngo Molnar 
42186470930SIngo Molnar 	for (i = 1; i < argc; i++)
42286470930SIngo Molnar 		fprintf(stderr, " %s", argv[i]);
42386470930SIngo Molnar 
42442202dd5SIngo Molnar 	fprintf(stderr, "\'");
42542202dd5SIngo Molnar 	if (run_count > 1)
42642202dd5SIngo Molnar 		fprintf(stderr, " (%d runs)", run_count);
42742202dd5SIngo Molnar 	fprintf(stderr, ":\n\n");
42886470930SIngo Molnar 
42986470930SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
43086470930SIngo Molnar 		print_counter(counter);
43186470930SIngo Molnar 
43286470930SIngo Molnar 
43386470930SIngo Molnar 	fprintf(stderr, "\n");
43442202dd5SIngo Molnar 	fprintf(stderr, " %14.9f  seconds time elapsed.\n",
43542202dd5SIngo Molnar 			(double)walltime_nsecs_avg/1e9);
43686470930SIngo Molnar 	fprintf(stderr, "\n");
43786470930SIngo Molnar }
43886470930SIngo Molnar 
439f7b7c26eSPeter Zijlstra static volatile int signr = -1;
440f7b7c26eSPeter Zijlstra 
44186470930SIngo Molnar static void skip_signal(int signo)
44286470930SIngo Molnar {
443f7b7c26eSPeter Zijlstra 	signr = signo;
444f7b7c26eSPeter Zijlstra }
445f7b7c26eSPeter Zijlstra 
446f7b7c26eSPeter Zijlstra static void sig_atexit(void)
447f7b7c26eSPeter Zijlstra {
448f7b7c26eSPeter Zijlstra 	if (signr == -1)
449f7b7c26eSPeter Zijlstra 		return;
450f7b7c26eSPeter Zijlstra 
451f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
452f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
45386470930SIngo Molnar }
45486470930SIngo Molnar 
45586470930SIngo Molnar static const char * const stat_usage[] = {
45686470930SIngo Molnar 	"perf stat [<options>] <command>",
45786470930SIngo Molnar 	NULL
45886470930SIngo Molnar };
45986470930SIngo Molnar 
46086470930SIngo Molnar static const struct option options[] = {
46186470930SIngo Molnar 	OPT_CALLBACK('e', "event", NULL, "event",
46286470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
46386470930SIngo Molnar 		     parse_events),
46486470930SIngo Molnar 	OPT_BOOLEAN('i', "inherit", &inherit,
46586470930SIngo Molnar 		    "child tasks inherit counters"),
46686470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
46786470930SIngo Molnar 		    "stat events on existing pid"),
46886470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
46986470930SIngo Molnar 			    "system-wide collection from all CPUs"),
47086470930SIngo Molnar 	OPT_BOOLEAN('S', "scale", &scale,
47186470930SIngo Molnar 			    "scale/normalize counters"),
472743ee1f8SIngo Molnar 	OPT_BOOLEAN('v', "verbose", &verbose,
473743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
47442202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
47542202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
47686470930SIngo Molnar 	OPT_END()
47786470930SIngo Molnar };
47886470930SIngo Molnar 
47986470930SIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix)
48086470930SIngo Molnar {
48142202dd5SIngo Molnar 	int status;
48242202dd5SIngo Molnar 
48386470930SIngo Molnar 	page_size = sysconf(_SC_PAGE_SIZE);
48486470930SIngo Molnar 
48586470930SIngo Molnar 	memcpy(attrs, default_attrs, sizeof(attrs));
48686470930SIngo Molnar 
48786470930SIngo Molnar 	argc = parse_options(argc, argv, options, stat_usage, 0);
48886470930SIngo Molnar 	if (!argc)
48986470930SIngo Molnar 		usage_with_options(stat_usage, options);
49042202dd5SIngo Molnar 	if (run_count <= 0 || run_count > MAX_RUN)
49142202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
49286470930SIngo Molnar 
49386470930SIngo Molnar 	if (!nr_counters)
49486470930SIngo Molnar 		nr_counters = 8;
49586470930SIngo Molnar 
49686470930SIngo Molnar 	nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
49786470930SIngo Molnar 	assert(nr_cpus <= MAX_NR_CPUS);
49886470930SIngo Molnar 	assert(nr_cpus >= 0);
49986470930SIngo Molnar 
50086470930SIngo Molnar 	/*
50186470930SIngo Molnar 	 * We dont want to block the signals - that would cause
50286470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
50386470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
50486470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
50586470930SIngo Molnar 	 */
506f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
50786470930SIngo Molnar 	signal(SIGINT,  skip_signal);
50886470930SIngo Molnar 	signal(SIGALRM, skip_signal);
50986470930SIngo Molnar 	signal(SIGABRT, skip_signal);
51086470930SIngo Molnar 
51142202dd5SIngo Molnar 	status = 0;
51242202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
51342202dd5SIngo Molnar 		if (run_count != 1 && verbose)
51442202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1);
51542202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
51642202dd5SIngo Molnar 	}
51742202dd5SIngo Molnar 
51842202dd5SIngo Molnar 	print_stat(argc, argv);
51942202dd5SIngo Molnar 
52042202dd5SIngo Molnar 	return status;
52186470930SIngo Molnar }
522