xref: /openbmc/linux/tools/perf/builtin-stat.c (revision c3043569)
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>
356e750a8fSJaswinder Singh Rajput  *   Jaswinder Singh Rajput <jaswinder@kernel.org>
3686470930SIngo Molnar  *
3786470930SIngo Molnar  * Released under the GPL v2. (and only v2, not any later version)
3886470930SIngo Molnar  */
3986470930SIngo Molnar 
4086470930SIngo Molnar #include "perf.h"
4186470930SIngo Molnar #include "builtin.h"
4286470930SIngo Molnar #include "util/util.h"
4386470930SIngo Molnar #include "util/parse-options.h"
4486470930SIngo Molnar #include "util/parse-events.h"
4586470930SIngo Molnar 
4686470930SIngo Molnar #include <sys/prctl.h>
4742202dd5SIngo Molnar #include <math.h>
4886470930SIngo Molnar 
49c3043569SJaswinder Singh Rajput static struct perf_counter_attr default_attrs[] = {
5086470930SIngo Molnar 
51f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK	},
52f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
53f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS	},
54f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS	},
5586470930SIngo Molnar 
56f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES	},
57f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS	},
58f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES},
59f4dbfa8fSPeter Zijlstra   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES	},
60f4dbfa8fSPeter Zijlstra 
6186470930SIngo Molnar };
6286470930SIngo Molnar 
6342202dd5SIngo Molnar #define MAX_RUN			100
6486470930SIngo Molnar 
653d632595SJaswinder Singh Rajput static int			system_wide			=  0;
663d632595SJaswinder Singh Rajput static int			verbose				=  0;
673d632595SJaswinder Singh Rajput static int			nr_cpus				=  0;
6842202dd5SIngo Molnar static int			run_idx				=  0;
6942202dd5SIngo Molnar 
703d632595SJaswinder Singh Rajput static int			run_count			=  1;
713d632595SJaswinder Singh Rajput static int			inherit				=  1;
723d632595SJaswinder Singh Rajput static int			scale				=  1;
733d632595SJaswinder Singh Rajput static int			target_pid			= -1;
740cfb7a13SIngo Molnar static int			null_run			=  0;
7542202dd5SIngo Molnar 
763d632595SJaswinder Singh Rajput static int			fd[MAX_NR_CPUS][MAX_COUNTERS];
7742202dd5SIngo Molnar 
789cffa8d5SPaul Mackerras static u64			runtime_nsecs[MAX_RUN];
799cffa8d5SPaul Mackerras static u64			walltime_nsecs[MAX_RUN];
809cffa8d5SPaul Mackerras static u64			runtime_cycles[MAX_RUN];
8142202dd5SIngo Molnar 
823d632595SJaswinder Singh Rajput static u64			event_res[MAX_RUN][MAX_COUNTERS][3];
833d632595SJaswinder Singh Rajput static u64			event_scaled[MAX_RUN][MAX_COUNTERS];
843d632595SJaswinder Singh Rajput 
859cffa8d5SPaul Mackerras static u64			event_res_avg[MAX_COUNTERS][3];
869cffa8d5SPaul Mackerras static u64			event_res_noise[MAX_COUNTERS][3];
8742202dd5SIngo Molnar 
889cffa8d5SPaul Mackerras static u64			event_scaled_avg[MAX_COUNTERS];
8942202dd5SIngo Molnar 
909cffa8d5SPaul Mackerras static u64			runtime_nsecs_avg;
919cffa8d5SPaul Mackerras static u64			runtime_nsecs_noise;
9242202dd5SIngo Molnar 
939cffa8d5SPaul Mackerras static u64			walltime_nsecs_avg;
949cffa8d5SPaul Mackerras static u64			walltime_nsecs_noise;
9542202dd5SIngo Molnar 
969cffa8d5SPaul Mackerras static u64			runtime_cycles_avg;
979cffa8d5SPaul Mackerras static u64			runtime_cycles_noise;
9886470930SIngo Molnar 
99cca03c0aSJaswinder Singh Rajput #define ERR_PERF_OPEN \
100cca03c0aSJaswinder Singh Rajput "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
101cca03c0aSJaswinder Singh Rajput 
102743ee1f8SIngo Molnar static void create_perf_stat_counter(int counter)
10386470930SIngo Molnar {
10486470930SIngo Molnar 	struct perf_counter_attr *attr = attrs + counter;
10586470930SIngo Molnar 
10686470930SIngo Molnar 	if (scale)
10786470930SIngo Molnar 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
10886470930SIngo Molnar 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
10986470930SIngo Molnar 
11086470930SIngo Molnar 	if (system_wide) {
11186470930SIngo Molnar 		int cpu;
11286470930SIngo Molnar 		for (cpu = 0; cpu < nr_cpus; cpu++) {
11386470930SIngo Molnar 			fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
114cca03c0aSJaswinder Singh Rajput 			if (fd[cpu][counter] < 0 && verbose)
115cca03c0aSJaswinder Singh Rajput 				fprintf(stderr, ERR_PERF_OPEN, counter,
116cca03c0aSJaswinder Singh Rajput 					fd[cpu][counter], strerror(errno));
11786470930SIngo Molnar 		}
11886470930SIngo Molnar 	} else {
11986470930SIngo Molnar 		attr->inherit	= inherit;
12086470930SIngo Molnar 		attr->disabled	= 1;
12186470930SIngo Molnar 
12286470930SIngo Molnar 		fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0);
123cca03c0aSJaswinder Singh Rajput 		if (fd[0][counter] < 0 && verbose)
124cca03c0aSJaswinder Singh Rajput 			fprintf(stderr, ERR_PERF_OPEN, counter,
125cca03c0aSJaswinder Singh Rajput 				fd[0][counter], strerror(errno));
12686470930SIngo Molnar 	}
12786470930SIngo Molnar }
12886470930SIngo Molnar 
12986470930SIngo Molnar /*
13086470930SIngo Molnar  * Does the counter have nsecs as a unit?
13186470930SIngo Molnar  */
13286470930SIngo Molnar static inline int nsec_counter(int counter)
13386470930SIngo Molnar {
13486470930SIngo Molnar 	if (attrs[counter].type != PERF_TYPE_SOFTWARE)
13586470930SIngo Molnar 		return 0;
13686470930SIngo Molnar 
137f4dbfa8fSPeter Zijlstra 	if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
13886470930SIngo Molnar 		return 1;
13986470930SIngo Molnar 
140f4dbfa8fSPeter Zijlstra 	if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
14186470930SIngo Molnar 		return 1;
14286470930SIngo Molnar 
14386470930SIngo Molnar 	return 0;
14486470930SIngo Molnar }
14586470930SIngo Molnar 
14686470930SIngo Molnar /*
14786470930SIngo Molnar  * Read out the results of a single counter:
14886470930SIngo Molnar  */
14986470930SIngo Molnar static void read_counter(int counter)
15086470930SIngo Molnar {
1519cffa8d5SPaul Mackerras 	u64 *count, single_count[3];
15286470930SIngo Molnar 	ssize_t res;
15386470930SIngo Molnar 	int cpu, nv;
15486470930SIngo Molnar 	int scaled;
15586470930SIngo Molnar 
15642202dd5SIngo Molnar 	count = event_res[run_idx][counter];
15786470930SIngo Molnar 
15886470930SIngo Molnar 	count[0] = count[1] = count[2] = 0;
15986470930SIngo Molnar 
16086470930SIngo Molnar 	nv = scale ? 3 : 1;
16186470930SIngo Molnar 	for (cpu = 0; cpu < nr_cpus; cpu++) {
162743ee1f8SIngo Molnar 		if (fd[cpu][counter] < 0)
163743ee1f8SIngo Molnar 			continue;
164743ee1f8SIngo Molnar 
1659cffa8d5SPaul Mackerras 		res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
1669cffa8d5SPaul Mackerras 		assert(res == nv * sizeof(u64));
16742202dd5SIngo Molnar 		close(fd[cpu][counter]);
16842202dd5SIngo Molnar 		fd[cpu][counter] = -1;
16986470930SIngo Molnar 
17086470930SIngo Molnar 		count[0] += single_count[0];
17186470930SIngo Molnar 		if (scale) {
17286470930SIngo Molnar 			count[1] += single_count[1];
17386470930SIngo Molnar 			count[2] += single_count[2];
17486470930SIngo Molnar 		}
17586470930SIngo Molnar 	}
17686470930SIngo Molnar 
17786470930SIngo Molnar 	scaled = 0;
17886470930SIngo Molnar 	if (scale) {
17986470930SIngo Molnar 		if (count[2] == 0) {
18042202dd5SIngo Molnar 			event_scaled[run_idx][counter] = -1;
18186470930SIngo Molnar 			count[0] = 0;
18286470930SIngo Molnar 			return;
18386470930SIngo Molnar 		}
18486470930SIngo Molnar 
18586470930SIngo Molnar 		if (count[2] < count[1]) {
18642202dd5SIngo Molnar 			event_scaled[run_idx][counter] = 1;
18786470930SIngo Molnar 			count[0] = (unsigned long long)
18886470930SIngo Molnar 				((double)count[0] * count[1] / count[2] + 0.5);
18986470930SIngo Molnar 		}
19086470930SIngo Molnar 	}
19186470930SIngo Molnar 	/*
19286470930SIngo Molnar 	 * Save the full runtime - to allow normalization during printout:
19386470930SIngo Molnar 	 */
19486470930SIngo Molnar 	if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
195f4dbfa8fSPeter Zijlstra 		attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
19642202dd5SIngo Molnar 		runtime_nsecs[run_idx] = count[0];
197e779898aSIngo Molnar 	if (attrs[counter].type == PERF_TYPE_HARDWARE &&
198f4dbfa8fSPeter Zijlstra 		attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
19942202dd5SIngo Molnar 		runtime_cycles[run_idx] = count[0];
20086470930SIngo Molnar }
20186470930SIngo Molnar 
20242202dd5SIngo Molnar static int run_perf_stat(int argc, const char **argv)
20386470930SIngo Molnar {
20486470930SIngo Molnar 	unsigned long long t0, t1;
20542202dd5SIngo Molnar 	int status = 0;
20686470930SIngo Molnar 	int counter;
20786470930SIngo Molnar 	int pid;
20886470930SIngo Molnar 
20986470930SIngo Molnar 	if (!system_wide)
21086470930SIngo Molnar 		nr_cpus = 1;
21186470930SIngo Molnar 
21286470930SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
213743ee1f8SIngo Molnar 		create_perf_stat_counter(counter);
21486470930SIngo Molnar 
21586470930SIngo Molnar 	/*
21686470930SIngo Molnar 	 * Enable counters and exec the command:
21786470930SIngo Molnar 	 */
21886470930SIngo Molnar 	t0 = rdclock();
21986470930SIngo Molnar 	prctl(PR_TASK_PERF_COUNTERS_ENABLE);
22086470930SIngo Molnar 
22186470930SIngo Molnar 	if ((pid = fork()) < 0)
22286470930SIngo Molnar 		perror("failed to fork");
22386470930SIngo Molnar 
22486470930SIngo Molnar 	if (!pid) {
22586470930SIngo Molnar 		if (execvp(argv[0], (char **)argv)) {
22686470930SIngo Molnar 			perror(argv[0]);
22786470930SIngo Molnar 			exit(-1);
22886470930SIngo Molnar 		}
22986470930SIngo Molnar 	}
23086470930SIngo Molnar 
23142202dd5SIngo Molnar 	wait(&status);
23286470930SIngo Molnar 
23386470930SIngo Molnar 	prctl(PR_TASK_PERF_COUNTERS_DISABLE);
23486470930SIngo Molnar 	t1 = rdclock();
23586470930SIngo Molnar 
23642202dd5SIngo Molnar 	walltime_nsecs[run_idx] = t1 - t0;
23742202dd5SIngo Molnar 
23842202dd5SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
23942202dd5SIngo Molnar 		read_counter(counter);
24042202dd5SIngo Molnar 
24142202dd5SIngo Molnar 	return WEXITSTATUS(status);
24242202dd5SIngo Molnar }
24342202dd5SIngo Molnar 
2449cffa8d5SPaul Mackerras static void print_noise(u64 *count, u64 *noise)
24542202dd5SIngo Molnar {
24642202dd5SIngo Molnar 	if (run_count > 1)
24742202dd5SIngo Molnar 		fprintf(stderr, "   ( +- %7.3f%% )",
24842202dd5SIngo Molnar 			(double)noise[0]/(count[0]+1)*100.0);
24942202dd5SIngo Molnar }
25042202dd5SIngo Molnar 
2519cffa8d5SPaul Mackerras static void nsec_printout(int counter, u64 *count, u64 *noise)
25242202dd5SIngo Molnar {
25342202dd5SIngo Molnar 	double msecs = (double)count[0] / 1000000;
25442202dd5SIngo Molnar 
2556e750a8fSJaswinder Singh Rajput 	fprintf(stderr, " %14.6f  %-24s", msecs, event_name(counter));
25642202dd5SIngo Molnar 
25742202dd5SIngo Molnar 	if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
25842202dd5SIngo Molnar 		attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
25942202dd5SIngo Molnar 
26042202dd5SIngo Molnar 		if (walltime_nsecs_avg)
26142202dd5SIngo Molnar 			fprintf(stderr, " # %10.3f CPUs ",
26242202dd5SIngo Molnar 				(double)count[0] / (double)walltime_nsecs_avg);
26342202dd5SIngo Molnar 	}
26442202dd5SIngo Molnar 	print_noise(count, noise);
26542202dd5SIngo Molnar }
26642202dd5SIngo Molnar 
2679cffa8d5SPaul Mackerras static void abs_printout(int counter, u64 *count, u64 *noise)
26842202dd5SIngo Molnar {
2696e750a8fSJaswinder Singh Rajput 	fprintf(stderr, " %14Ld  %-24s", count[0], event_name(counter));
27042202dd5SIngo Molnar 
27142202dd5SIngo Molnar 	if (runtime_cycles_avg &&
27242202dd5SIngo Molnar 		attrs[counter].type == PERF_TYPE_HARDWARE &&
27342202dd5SIngo Molnar 			attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
27442202dd5SIngo Molnar 
27542202dd5SIngo Molnar 		fprintf(stderr, " # %10.3f IPC  ",
27642202dd5SIngo Molnar 			(double)count[0] / (double)runtime_cycles_avg);
27742202dd5SIngo Molnar 	} else {
27842202dd5SIngo Molnar 		if (runtime_nsecs_avg) {
27942202dd5SIngo Molnar 			fprintf(stderr, " # %10.3f M/sec",
28042202dd5SIngo Molnar 				(double)count[0]/runtime_nsecs_avg*1000.0);
28142202dd5SIngo Molnar 		}
28242202dd5SIngo Molnar 	}
28342202dd5SIngo Molnar 	print_noise(count, noise);
28442202dd5SIngo Molnar }
28542202dd5SIngo Molnar 
28642202dd5SIngo Molnar /*
28742202dd5SIngo Molnar  * Print out the results of a single counter:
28842202dd5SIngo Molnar  */
28942202dd5SIngo Molnar static void print_counter(int counter)
29042202dd5SIngo Molnar {
2919cffa8d5SPaul Mackerras 	u64 *count, *noise;
29242202dd5SIngo Molnar 	int scaled;
29342202dd5SIngo Molnar 
29442202dd5SIngo Molnar 	count = event_res_avg[counter];
29542202dd5SIngo Molnar 	noise = event_res_noise[counter];
29642202dd5SIngo Molnar 	scaled = event_scaled_avg[counter];
29742202dd5SIngo Molnar 
29842202dd5SIngo Molnar 	if (scaled == -1) {
2996e750a8fSJaswinder Singh Rajput 		fprintf(stderr, " %14s  %-24s\n",
30042202dd5SIngo Molnar 			"<not counted>", event_name(counter));
30142202dd5SIngo Molnar 		return;
30242202dd5SIngo Molnar 	}
30342202dd5SIngo Molnar 
30442202dd5SIngo Molnar 	if (nsec_counter(counter))
30542202dd5SIngo Molnar 		nsec_printout(counter, count, noise);
30642202dd5SIngo Molnar 	else
30742202dd5SIngo Molnar 		abs_printout(counter, count, noise);
30842202dd5SIngo Molnar 
30942202dd5SIngo Molnar 	if (scaled)
3106e750a8fSJaswinder Singh Rajput 		fprintf(stderr, "  (%7.2fx scaled)", (double)count[1]/count[2]);
31142202dd5SIngo Molnar 
31242202dd5SIngo Molnar 	fprintf(stderr, "\n");
31342202dd5SIngo Molnar }
31442202dd5SIngo Molnar 
31542202dd5SIngo Molnar /*
316ef281a19SIngo Molnar  * normalize_noise noise values down to stddev:
31742202dd5SIngo Molnar  */
3189cffa8d5SPaul Mackerras static void normalize_noise(u64 *val)
31942202dd5SIngo Molnar {
32042202dd5SIngo Molnar 	double res;
32142202dd5SIngo Molnar 
32242202dd5SIngo Molnar 	res = (double)*val / (run_count * sqrt((double)run_count));
32342202dd5SIngo Molnar 
3249cffa8d5SPaul Mackerras 	*val = (u64)res;
32542202dd5SIngo Molnar }
32642202dd5SIngo Molnar 
3279cffa8d5SPaul Mackerras static void update_avg(const char *name, int idx, u64 *avg, u64 *val)
328ef281a19SIngo Molnar {
329ef281a19SIngo Molnar 	*avg += *val;
330ef281a19SIngo Molnar 
331ef281a19SIngo Molnar 	if (verbose > 1)
332ef281a19SIngo Molnar 		fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val);
333ef281a19SIngo Molnar }
33442202dd5SIngo Molnar /*
33542202dd5SIngo Molnar  * Calculate the averages and noises:
33642202dd5SIngo Molnar  */
33742202dd5SIngo Molnar static void calc_avg(void)
33842202dd5SIngo Molnar {
33942202dd5SIngo Molnar 	int i, j;
34042202dd5SIngo Molnar 
341ef281a19SIngo Molnar 	if (verbose > 1)
342ef281a19SIngo Molnar 		fprintf(stderr, "\n");
343ef281a19SIngo Molnar 
34442202dd5SIngo Molnar 	for (i = 0; i < run_count; i++) {
345ef281a19SIngo Molnar 		update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i);
346ef281a19SIngo Molnar 		update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i);
347ef281a19SIngo Molnar 		update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i);
34842202dd5SIngo Molnar 
34942202dd5SIngo Molnar 		for (j = 0; j < nr_counters; j++) {
350ef281a19SIngo Molnar 			update_avg("counter/0", j,
351ef281a19SIngo Molnar 				event_res_avg[j]+0, event_res[i][j]+0);
352ef281a19SIngo Molnar 			update_avg("counter/1", j,
353ef281a19SIngo Molnar 				event_res_avg[j]+1, event_res[i][j]+1);
354ef281a19SIngo Molnar 			update_avg("counter/2", j,
355ef281a19SIngo Molnar 				event_res_avg[j]+2, event_res[i][j]+2);
356566747e6SIngo Molnar 			if (event_scaled[i][j] != -1)
357ef281a19SIngo Molnar 				update_avg("scaled", j,
358ef281a19SIngo Molnar 					event_scaled_avg + j, event_scaled[i]+j);
359566747e6SIngo Molnar 			else
360566747e6SIngo Molnar 				event_scaled_avg[j] = -1;
36142202dd5SIngo Molnar 		}
36242202dd5SIngo Molnar 	}
36342202dd5SIngo Molnar 	runtime_nsecs_avg /= run_count;
36442202dd5SIngo Molnar 	walltime_nsecs_avg /= run_count;
36542202dd5SIngo Molnar 	runtime_cycles_avg /= run_count;
36642202dd5SIngo Molnar 
36742202dd5SIngo Molnar 	for (j = 0; j < nr_counters; j++) {
36842202dd5SIngo Molnar 		event_res_avg[j][0] /= run_count;
36942202dd5SIngo Molnar 		event_res_avg[j][1] /= run_count;
37042202dd5SIngo Molnar 		event_res_avg[j][2] /= run_count;
37142202dd5SIngo Molnar 	}
37242202dd5SIngo Molnar 
37342202dd5SIngo Molnar 	for (i = 0; i < run_count; i++) {
37442202dd5SIngo Molnar 		runtime_nsecs_noise +=
3759cffa8d5SPaul Mackerras 			abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg));
37642202dd5SIngo Molnar 		walltime_nsecs_noise +=
3779cffa8d5SPaul Mackerras 			abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg));
37842202dd5SIngo Molnar 		runtime_cycles_noise +=
3799cffa8d5SPaul Mackerras 			abs((s64)(runtime_cycles[i] - runtime_cycles_avg));
38042202dd5SIngo Molnar 
38142202dd5SIngo Molnar 		for (j = 0; j < nr_counters; j++) {
38242202dd5SIngo Molnar 			event_res_noise[j][0] +=
3839cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][0] - event_res_avg[j][0]));
38442202dd5SIngo Molnar 			event_res_noise[j][1] +=
3859cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][1] - event_res_avg[j][1]));
38642202dd5SIngo Molnar 			event_res_noise[j][2] +=
3879cffa8d5SPaul Mackerras 				abs((s64)(event_res[i][j][2] - event_res_avg[j][2]));
38842202dd5SIngo Molnar 		}
38942202dd5SIngo Molnar 	}
39042202dd5SIngo Molnar 
391ef281a19SIngo Molnar 	normalize_noise(&runtime_nsecs_noise);
392ef281a19SIngo Molnar 	normalize_noise(&walltime_nsecs_noise);
393ef281a19SIngo Molnar 	normalize_noise(&runtime_cycles_noise);
39442202dd5SIngo Molnar 
39542202dd5SIngo Molnar 	for (j = 0; j < nr_counters; j++) {
396ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][0]);
397ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][1]);
398ef281a19SIngo Molnar 		normalize_noise(&event_res_noise[j][2]);
39942202dd5SIngo Molnar 	}
40042202dd5SIngo Molnar }
40142202dd5SIngo Molnar 
40242202dd5SIngo Molnar static void print_stat(int argc, const char **argv)
40342202dd5SIngo Molnar {
40442202dd5SIngo Molnar 	int i, counter;
40542202dd5SIngo Molnar 
40642202dd5SIngo Molnar 	calc_avg();
40742202dd5SIngo Molnar 
40886470930SIngo Molnar 	fflush(stdout);
40986470930SIngo Molnar 
41086470930SIngo Molnar 	fprintf(stderr, "\n");
41186470930SIngo Molnar 	fprintf(stderr, " Performance counter stats for \'%s", argv[0]);
41286470930SIngo Molnar 
41386470930SIngo Molnar 	for (i = 1; i < argc; i++)
41486470930SIngo Molnar 		fprintf(stderr, " %s", argv[i]);
41586470930SIngo Molnar 
41642202dd5SIngo Molnar 	fprintf(stderr, "\'");
41742202dd5SIngo Molnar 	if (run_count > 1)
41842202dd5SIngo Molnar 		fprintf(stderr, " (%d runs)", run_count);
41942202dd5SIngo Molnar 	fprintf(stderr, ":\n\n");
42086470930SIngo Molnar 
42186470930SIngo Molnar 	for (counter = 0; counter < nr_counters; counter++)
42286470930SIngo Molnar 		print_counter(counter);
42386470930SIngo Molnar 
42486470930SIngo Molnar 	fprintf(stderr, "\n");
425566747e6SIngo Molnar 	fprintf(stderr, " %14.9f  seconds time elapsed",
42642202dd5SIngo Molnar 			(double)walltime_nsecs_avg/1e9);
427566747e6SIngo Molnar 	if (run_count > 1) {
428566747e6SIngo Molnar 		fprintf(stderr, "   ( +- %7.3f%% )",
429566747e6SIngo Molnar 			100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg);
430566747e6SIngo Molnar 	}
431566747e6SIngo Molnar 	fprintf(stderr, "\n\n");
43286470930SIngo Molnar }
43386470930SIngo Molnar 
434f7b7c26eSPeter Zijlstra static volatile int signr = -1;
435f7b7c26eSPeter Zijlstra 
43686470930SIngo Molnar static void skip_signal(int signo)
43786470930SIngo Molnar {
438f7b7c26eSPeter Zijlstra 	signr = signo;
439f7b7c26eSPeter Zijlstra }
440f7b7c26eSPeter Zijlstra 
441f7b7c26eSPeter Zijlstra static void sig_atexit(void)
442f7b7c26eSPeter Zijlstra {
443f7b7c26eSPeter Zijlstra 	if (signr == -1)
444f7b7c26eSPeter Zijlstra 		return;
445f7b7c26eSPeter Zijlstra 
446f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
447f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
44886470930SIngo Molnar }
44986470930SIngo Molnar 
45086470930SIngo Molnar static const char * const stat_usage[] = {
45186470930SIngo Molnar 	"perf stat [<options>] <command>",
45286470930SIngo Molnar 	NULL
45386470930SIngo Molnar };
45486470930SIngo Molnar 
45586470930SIngo Molnar static const struct option options[] = {
45686470930SIngo Molnar 	OPT_CALLBACK('e', "event", NULL, "event",
45786470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
45886470930SIngo Molnar 		     parse_events),
45986470930SIngo Molnar 	OPT_BOOLEAN('i', "inherit", &inherit,
46086470930SIngo Molnar 		    "child tasks inherit counters"),
46186470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
46286470930SIngo Molnar 		    "stat events on existing pid"),
46386470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
46486470930SIngo Molnar 		    "system-wide collection from all CPUs"),
46586470930SIngo Molnar 	OPT_BOOLEAN('S', "scale", &scale,
46686470930SIngo Molnar 		    "scale/normalize counters"),
467743ee1f8SIngo Molnar 	OPT_BOOLEAN('v', "verbose", &verbose,
468743ee1f8SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
46942202dd5SIngo Molnar 	OPT_INTEGER('r', "repeat", &run_count,
47042202dd5SIngo Molnar 		    "repeat command and print average + stddev (max: 100)"),
4710cfb7a13SIngo Molnar 	OPT_BOOLEAN('n', "null", &null_run,
4720cfb7a13SIngo Molnar 		    "null run - dont start any counters"),
47386470930SIngo Molnar 	OPT_END()
47486470930SIngo Molnar };
47586470930SIngo Molnar 
47686470930SIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix)
47786470930SIngo Molnar {
47842202dd5SIngo Molnar 	int status;
47942202dd5SIngo Molnar 
48086470930SIngo Molnar 	argc = parse_options(argc, argv, options, stat_usage, 0);
48186470930SIngo Molnar 	if (!argc)
48286470930SIngo Molnar 		usage_with_options(stat_usage, options);
48342202dd5SIngo Molnar 	if (run_count <= 0 || run_count > MAX_RUN)
48442202dd5SIngo Molnar 		usage_with_options(stat_usage, options);
48586470930SIngo Molnar 
486c3043569SJaswinder Singh Rajput 	/* Set attrs and nr_counters if no event is selected and !null_run */
487c3043569SJaswinder Singh Rajput 	if (!null_run && !nr_counters) {
488c3043569SJaswinder Singh Rajput 		memcpy(attrs, default_attrs, sizeof(default_attrs));
489c3043569SJaswinder Singh Rajput 		nr_counters = ARRAY_SIZE(default_attrs);
490c3043569SJaswinder Singh Rajput 	}
49186470930SIngo Molnar 
49286470930SIngo Molnar 	nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
49386470930SIngo Molnar 	assert(nr_cpus <= MAX_NR_CPUS);
49486470930SIngo Molnar 	assert(nr_cpus >= 0);
49586470930SIngo Molnar 
49686470930SIngo Molnar 	/*
49786470930SIngo Molnar 	 * We dont want to block the signals - that would cause
49886470930SIngo Molnar 	 * child tasks to inherit that and Ctrl-C would not work.
49986470930SIngo Molnar 	 * What we want is for Ctrl-C to work in the exec()-ed
50086470930SIngo Molnar 	 * task, but being ignored by perf stat itself:
50186470930SIngo Molnar 	 */
502f7b7c26eSPeter Zijlstra 	atexit(sig_atexit);
50386470930SIngo Molnar 	signal(SIGINT,  skip_signal);
50486470930SIngo Molnar 	signal(SIGALRM, skip_signal);
50586470930SIngo Molnar 	signal(SIGABRT, skip_signal);
50686470930SIngo Molnar 
50742202dd5SIngo Molnar 	status = 0;
50842202dd5SIngo Molnar 	for (run_idx = 0; run_idx < run_count; run_idx++) {
50942202dd5SIngo Molnar 		if (run_count != 1 && verbose)
51042202dd5SIngo Molnar 			fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
51142202dd5SIngo Molnar 		status = run_perf_stat(argc, argv);
51242202dd5SIngo Molnar 	}
51342202dd5SIngo Molnar 
51442202dd5SIngo Molnar 	print_stat(argc, argv);
51542202dd5SIngo Molnar 
51642202dd5SIngo Molnar 	return status;
51786470930SIngo Molnar }
518