};
+#define MAX_RUN 100
+
static int system_wide = 0;
-static int inherit = 1;
static int verbose = 0;
-
-static int fd[MAX_NR_CPUS][MAX_COUNTERS];
-
-static int target_pid = -1;
static int nr_cpus = 0;
-static unsigned int page_size;
+static int run_idx = 0;
+static int run_count = 1;
+static int inherit = 1;
static int scale = 1;
+static int target_pid = -1;
+static int null_run = 0;
-static const unsigned int default_count[] = {
- 1000000,
- 1000000,
- 10000,
- 10000,
- 1000000,
- 10000,
-};
-
-#define MAX_RUN 100
-
-static int run_count = 1;
-static int run_idx = 0;
-
-static __u64 event_res[MAX_RUN][MAX_COUNTERS][3];
-static __u64 event_scaled[MAX_RUN][MAX_COUNTERS];
+static int fd[MAX_NR_CPUS][MAX_COUNTERS];
-//static __u64 event_hist[MAX_RUN][MAX_COUNTERS][3];
+static u64 runtime_nsecs[MAX_RUN];
+static u64 walltime_nsecs[MAX_RUN];
+static u64 runtime_cycles[MAX_RUN];
+static u64 event_res[MAX_RUN][MAX_COUNTERS][3];
+static u64 event_scaled[MAX_RUN][MAX_COUNTERS];
-static __u64 runtime_nsecs[MAX_RUN];
-static __u64 walltime_nsecs[MAX_RUN];
-static __u64 runtime_cycles[MAX_RUN];
+static u64 event_res_avg[MAX_COUNTERS][3];
+static u64 event_res_noise[MAX_COUNTERS][3];
-static __u64 event_res_avg[MAX_COUNTERS][3];
-static __u64 event_res_noise[MAX_COUNTERS][3];
+static u64 event_scaled_avg[MAX_COUNTERS];
-static __u64 event_scaled_avg[MAX_COUNTERS];
+static u64 runtime_nsecs_avg;
+static u64 runtime_nsecs_noise;
-static __u64 runtime_nsecs_avg;
-static __u64 runtime_nsecs_noise;
+static u64 walltime_nsecs_avg;
+static u64 walltime_nsecs_noise;
-static __u64 walltime_nsecs_avg;
-static __u64 walltime_nsecs_noise;
+static u64 runtime_cycles_avg;
+static u64 runtime_cycles_noise;
-static __u64 runtime_cycles_avg;
-static __u64 runtime_cycles_noise;
+#define ERR_PERF_OPEN \
+"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
static void create_perf_stat_counter(int counter)
{
if (system_wide) {
int cpu;
- for (cpu = 0; cpu < nr_cpus; cpu ++) {
+ for (cpu = 0; cpu < nr_cpus; cpu++) {
fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
- if (fd[cpu][counter] < 0 && verbose) {
- printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno));
- }
+ if (fd[cpu][counter] < 0 && verbose)
+ fprintf(stderr, ERR_PERF_OPEN, counter,
+ fd[cpu][counter], strerror(errno));
}
} else {
attr->inherit = inherit;
attr->disabled = 1;
fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0);
- if (fd[0][counter] < 0 && verbose) {
- printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno));
- }
+ if (fd[0][counter] < 0 && verbose)
+ fprintf(stderr, ERR_PERF_OPEN, counter,
+ fd[0][counter], strerror(errno));
}
}
*/
static void read_counter(int counter)
{
- __u64 *count, single_count[3];
+ u64 *count, single_count[3];
ssize_t res;
int cpu, nv;
int scaled;
count[0] = count[1] = count[2] = 0;
nv = scale ? 3 : 1;
- for (cpu = 0; cpu < nr_cpus; cpu ++) {
+ for (cpu = 0; cpu < nr_cpus; cpu++) {
if (fd[cpu][counter] < 0)
continue;
- res = read(fd[cpu][counter], single_count, nv * sizeof(__u64));
- assert(res == nv * sizeof(__u64));
+ res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
+ assert(res == nv * sizeof(u64));
close(fd[cpu][counter]);
fd[cpu][counter] = -1;
return WEXITSTATUS(status);
}
-static void print_noise(__u64 *count, __u64 *noise)
+static void print_noise(u64 *count, u64 *noise)
{
if (run_count > 1)
fprintf(stderr, " ( +- %7.3f%% )",
(double)noise[0]/(count[0]+1)*100.0);
}
-static void nsec_printout(int counter, __u64 *count, __u64 *noise)
+static void nsec_printout(int counter, u64 *count, u64 *noise)
{
double msecs = (double)count[0] / 1000000;
print_noise(count, noise);
}
-static void abs_printout(int counter, __u64 *count, __u64 *noise)
+static void abs_printout(int counter, u64 *count, u64 *noise)
{
fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter));
*/
static void print_counter(int counter)
{
- __u64 *count, *noise;
+ u64 *count, *noise;
int scaled;
count = event_res_avg[counter];
}
/*
- * Normalize noise values down to stddev:
+ * normalize_noise noise values down to stddev:
*/
-static void normalize(__u64 *val)
+static void normalize_noise(u64 *val)
{
double res;
res = (double)*val / (run_count * sqrt((double)run_count));
- *val = (__u64)res;
+ *val = (u64)res;
}
+static void update_avg(const char *name, int idx, u64 *avg, u64 *val)
+{
+ *avg += *val;
+
+ if (verbose > 1)
+ fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val);
+}
/*
* Calculate the averages and noises:
*/
{
int i, j;
+ if (verbose > 1)
+ fprintf(stderr, "\n");
+
for (i = 0; i < run_count; i++) {
- runtime_nsecs_avg += runtime_nsecs[i];
- walltime_nsecs_avg += walltime_nsecs[i];
- runtime_cycles_avg += runtime_cycles[i];
+ update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i);
+ update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i);
+ update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i);
for (j = 0; j < nr_counters; j++) {
- event_res_avg[j][0] += event_res[i][j][0];
- event_res_avg[j][1] += event_res[i][j][1];
- event_res_avg[j][2] += event_res[i][j][2];
- event_scaled_avg[j] += event_scaled[i][j];
+ update_avg("counter/0", j,
+ event_res_avg[j]+0, event_res[i][j]+0);
+ update_avg("counter/1", j,
+ event_res_avg[j]+1, event_res[i][j]+1);
+ update_avg("counter/2", j,
+ event_res_avg[j]+2, event_res[i][j]+2);
+ if (event_scaled[i][j] != -1)
+ update_avg("scaled", j,
+ event_scaled_avg + j, event_scaled[i]+j);
+ else
+ event_scaled_avg[j] = -1;
}
}
runtime_nsecs_avg /= run_count;
for (i = 0; i < run_count; i++) {
runtime_nsecs_noise +=
- abs((__s64)(runtime_nsecs[i] - runtime_nsecs_avg));
+ abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg));
walltime_nsecs_noise +=
- abs((__s64)(walltime_nsecs[i] - walltime_nsecs_avg));
+ abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg));
runtime_cycles_noise +=
- abs((__s64)(runtime_cycles[i] - runtime_cycles_avg));
+ abs((s64)(runtime_cycles[i] - runtime_cycles_avg));
for (j = 0; j < nr_counters; j++) {
event_res_noise[j][0] +=
- abs((__s64)(event_res[i][j][0] - event_res_avg[j][0]));
+ abs((s64)(event_res[i][j][0] - event_res_avg[j][0]));
event_res_noise[j][1] +=
- abs((__s64)(event_res[i][j][1] - event_res_avg[j][1]));
+ abs((s64)(event_res[i][j][1] - event_res_avg[j][1]));
event_res_noise[j][2] +=
- abs((__s64)(event_res[i][j][2] - event_res_avg[j][2]));
+ abs((s64)(event_res[i][j][2] - event_res_avg[j][2]));
}
}
- normalize(&runtime_nsecs_noise);
- normalize(&walltime_nsecs_noise);
- normalize(&runtime_cycles_noise);
+ normalize_noise(&runtime_nsecs_noise);
+ normalize_noise(&walltime_nsecs_noise);
+ normalize_noise(&runtime_cycles_noise);
for (j = 0; j < nr_counters; j++) {
- normalize(&event_res_noise[j][0]);
- normalize(&event_res_noise[j][1]);
- normalize(&event_res_noise[j][2]);
+ normalize_noise(&event_res_noise[j][0]);
+ normalize_noise(&event_res_noise[j][1]);
+ normalize_noise(&event_res_noise[j][2]);
}
}
calc_avg();
- run_idx = 0;
-
fflush(stdout);
fprintf(stderr, "\n");
fprintf(stderr, "\n");
- fprintf(stderr, " %14.9f seconds time elapsed.\n",
+ fprintf(stderr, " %14.9f seconds time elapsed",
(double)walltime_nsecs_avg/1e9);
- fprintf(stderr, "\n");
+ if (run_count > 1) {
+ fprintf(stderr, " ( +- %7.3f%% )",
+ 100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg);
+ }
+ fprintf(stderr, "\n\n");
}
static volatile int signr = -1;
OPT_INTEGER('p', "pid", &target_pid,
"stat events on existing pid"),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
- "system-wide collection from all CPUs"),
+ "system-wide collection from all CPUs"),
OPT_BOOLEAN('S', "scale", &scale,
- "scale/normalize counters"),
+ "scale/normalize counters"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_INTEGER('r', "repeat", &run_count,
"repeat command and print average + stddev (max: 100)"),
+ OPT_BOOLEAN('n', "null", &null_run,
+ "null run - dont start any counters"),
OPT_END()
};
{
int status;
- page_size = sysconf(_SC_PAGE_SIZE);
-
memcpy(attrs, default_attrs, sizeof(attrs));
argc = parse_options(argc, argv, options, stat_usage, 0);
if (run_count <= 0 || run_count > MAX_RUN)
usage_with_options(stat_usage, options);
- if (!nr_counters)
+ if (!null_run && !nr_counters)
nr_counters = 8;
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
status = 0;
for (run_idx = 0; run_idx < run_count; run_idx++) {
if (run_count != 1 && verbose)
- fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1);
+ fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
status = run_perf_stat(argc, argv);
}