builtin-stat.c (0588000eac9ba4178cebade437da3b28e8fad48f) builtin-stat.c (cac21425578abddc4e9f529845832a57ba27ce0f)
1/*
2 * builtin-stat.c
3 *
4 * Builtin stat command: Give a precise performance counters summary
5 * overview about any workload, CPU or specific PID.
6 *
7 * Sample output:
8

--- 43 unchanged lines hidden (view full) ---

52#include "util/debug.h"
53#include "util/color.h"
54#include "util/stat.h"
55#include "util/header.h"
56#include "util/cpumap.h"
57#include "util/thread.h"
58#include "util/thread_map.h"
59
1/*
2 * builtin-stat.c
3 *
4 * Builtin stat command: Give a precise performance counters summary
5 * overview about any workload, CPU or specific PID.
6 *
7 * Sample output:
8

--- 43 unchanged lines hidden (view full) ---

52#include "util/debug.h"
53#include "util/color.h"
54#include "util/stat.h"
55#include "util/header.h"
56#include "util/cpumap.h"
57#include "util/thread.h"
58#include "util/thread_map.h"
59
60#include <stdlib.h>
60#include <sys/prctl.h>
61#include <locale.h>
62
63#define DEFAULT_SEPARATOR " "
64#define CNTR_NOT_SUPPORTED "<not supported>"
65#define CNTR_NOT_COUNTED "<not counted>"
66
67static struct perf_evlist *evsel_list;

--- 10 unchanged lines hidden (view full) ---

78static bool null_run = false;
79static int detailed_run = 0;
80static bool big_num = true;
81static int big_num_opt = -1;
82static const char *csv_sep = NULL;
83static bool csv_output = false;
84static bool group = false;
85static FILE *output = NULL;
61#include <sys/prctl.h>
62#include <locale.h>
63
64#define DEFAULT_SEPARATOR " "
65#define CNTR_NOT_SUPPORTED "<not supported>"
66#define CNTR_NOT_COUNTED "<not counted>"
67
68static struct perf_evlist *evsel_list;

--- 10 unchanged lines hidden (view full) ---

79static bool null_run = false;
80static int detailed_run = 0;
81static bool big_num = true;
82static int big_num_opt = -1;
83static const char *csv_sep = NULL;
84static bool csv_output = false;
85static bool group = false;
86static FILE *output = NULL;
87static const char *pre_cmd = NULL;
88static const char *post_cmd = NULL;
89static bool sync_run = false;
86
87static volatile int done = 0;
88
89struct perf_stat {
90 struct stats res_stats[3];
91};
92
93static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)

--- 26 unchanged lines hidden (view full) ---

120static struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
121static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
122static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
123static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
124static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
125static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
126static struct stats walltime_nsecs_stats;
127
90
91static volatile int done = 0;
92
93struct perf_stat {
94 struct stats res_stats[3];
95};
96
97static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)

--- 26 unchanged lines hidden (view full) ---

124static struct stats runtime_cacherefs_stats[MAX_NR_CPUS];
125static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS];
126static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
127static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
128static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
129static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
130static struct stats walltime_nsecs_stats;
131
128static int create_perf_stat_counter(struct perf_evsel *evsel,
129 struct perf_evsel *first)
132static int create_perf_stat_counter(struct perf_evsel *evsel)
130{
131 struct perf_event_attr *attr = &evsel->attr;
132 bool exclude_guest_missing = false;
133 int ret;
134
135 if (scale)
136 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
137 PERF_FORMAT_TOTAL_TIME_RUNNING;

--- 6 unchanged lines hidden (view full) ---

144
145 if (perf_target__has_cpu(&target)) {
146 ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
147 if (ret)
148 goto check_ret;
149 return 0;
150 }
151
133{
134 struct perf_event_attr *attr = &evsel->attr;
135 bool exclude_guest_missing = false;
136 int ret;
137
138 if (scale)
139 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
140 PERF_FORMAT_TOTAL_TIME_RUNNING;

--- 6 unchanged lines hidden (view full) ---

147
148 if (perf_target__has_cpu(&target)) {
149 ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
150 if (ret)
151 goto check_ret;
152 return 0;
153 }
154
152 if (!perf_target__has_task(&target) && (!group || evsel == first)) {
155 if (!perf_target__has_task(&target) && (!evsel->leader)) {
153 attr->disabled = 1;
154 attr->enable_on_exec = 1;
155 }
156
157 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
158 if (!ret)
159 return 0;
160 /* fall through */

--- 99 unchanged lines hidden (view full) ---

260 count = counter->counts->cpu[cpu].values;
261
262 update_shadow_stats(counter, count);
263 }
264
265 return 0;
266}
267
156 attr->disabled = 1;
157 attr->enable_on_exec = 1;
158 }
159
160 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
161 if (!ret)
162 return 0;
163 /* fall through */

--- 99 unchanged lines hidden (view full) ---

263 count = counter->counts->cpu[cpu].values;
264
265 update_shadow_stats(counter, count);
266 }
267
268 return 0;
269}
270
268static int run_perf_stat(int argc __maybe_unused, const char **argv)
271static int __run_perf_stat(int argc __maybe_unused, const char **argv)
269{
270 unsigned long long t0, t1;
272{
273 unsigned long long t0, t1;
271 struct perf_evsel *counter, *first;
274 struct perf_evsel *counter;
272 int status = 0;
273 int child_ready_pipe[2], go_pipe[2];
274 const bool forks = (argc > 0);
275 char buf;
276
277 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
278 perror("failed to create pipes");
279 return -1;

--- 43 unchanged lines hidden (view full) ---

323 if (read(child_ready_pipe[0], &buf, 1) == -1)
324 perror("unable to read pipe");
325 close(child_ready_pipe[0]);
326 }
327
328 if (group)
329 perf_evlist__set_leader(evsel_list);
330
275 int status = 0;
276 int child_ready_pipe[2], go_pipe[2];
277 const bool forks = (argc > 0);
278 char buf;
279
280 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
281 perror("failed to create pipes");
282 return -1;

--- 43 unchanged lines hidden (view full) ---

326 if (read(child_ready_pipe[0], &buf, 1) == -1)
327 perror("unable to read pipe");
328 close(child_ready_pipe[0]);
329 }
330
331 if (group)
332 perf_evlist__set_leader(evsel_list);
333
331 first = perf_evlist__first(evsel_list);
332
333 list_for_each_entry(counter, &evsel_list->entries, node) {
334 list_for_each_entry(counter, &evsel_list->entries, node) {
334 if (create_perf_stat_counter(counter, first) < 0) {
335 if (create_perf_stat_counter(counter) < 0) {
335 /*
336 * PPC returns ENXIO for HW counters until 2.6.37
337 * (behavior changed with commit b0a873e).
338 */
339 if (errno == EINVAL || errno == ENOSYS ||
340 errno == ENOENT || errno == EOPNOTSUPP ||
341 errno == ENXIO) {
342 if (verbose)

--- 57 unchanged lines hidden (view full) ---

400 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
401 evsel_list->threads->nr);
402 }
403 }
404
405 return WEXITSTATUS(status);
406}
407
336 /*
337 * PPC returns ENXIO for HW counters until 2.6.37
338 * (behavior changed with commit b0a873e).
339 */
340 if (errno == EINVAL || errno == ENOSYS ||
341 errno == ENOENT || errno == EOPNOTSUPP ||
342 errno == ENXIO) {
343 if (verbose)

--- 57 unchanged lines hidden (view full) ---

401 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
402 evsel_list->threads->nr);
403 }
404 }
405
406 return WEXITSTATUS(status);
407}
408
409static int run_perf_stat(int argc __maybe_unused, const char **argv)
410{
411 int ret;
412
413 if (pre_cmd) {
414 ret = system(pre_cmd);
415 if (ret)
416 return ret;
417 }
418
419 if (sync_run)
420 sync();
421
422 ret = __run_perf_stat(argc, argv);
423 if (ret)
424 return ret;
425
426 if (post_cmd) {
427 ret = system(post_cmd);
428 if (ret)
429 return ret;
430 }
431
432 return ret;
433}
434
408static void print_noise_pct(double total, double avg)
409{
410 double pct = rel_stddev_stats(total, avg);
411
412 if (csv_output)
413 fprintf(output, "%s%.2f%%", csv_sep, pct);
414 else if (pct)
415 fprintf(output, " ( +-%6.2f%% )", pct);

--- 648 unchanged lines hidden (view full) ---

1064 return 0;
1065
1066 /* Append very, very detailed run extra attributes: */
1067 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1068}
1069
1070int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1071{
435static void print_noise_pct(double total, double avg)
436{
437 double pct = rel_stddev_stats(total, avg);
438
439 if (csv_output)
440 fprintf(output, "%s%.2f%%", csv_sep, pct);
441 else if (pct)
442 fprintf(output, " ( +-%6.2f%% )", pct);

--- 648 unchanged lines hidden (view full) ---

1091 return 0;
1092
1093 /* Append very, very detailed run extra attributes: */
1094 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1095}
1096
1097int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1098{
1072 bool append_file = false,
1073 sync_run = false;
1099 bool append_file = false;
1074 int output_fd = 0;
1075 const char *output_name = NULL;
1076 const struct option options[] = {
1077 OPT_CALLBACK('e', "event", &evsel_list, "event",
1078 "event selector. use 'perf list' to list available events",
1079 parse_events_option),
1080 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1081 "event filter", parse_filter),

--- 27 unchanged lines hidden (view full) ---

1109 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1110 "print counts with custom separator"),
1111 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1112 "monitor event in cgroup name only", parse_cgroups),
1113 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1114 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1115 OPT_INTEGER(0, "log-fd", &output_fd,
1116 "log output to fd, instead of stderr"),
1100 int output_fd = 0;
1101 const char *output_name = NULL;
1102 const struct option options[] = {
1103 OPT_CALLBACK('e', "event", &evsel_list, "event",
1104 "event selector. use 'perf list' to list available events",
1105 parse_events_option),
1106 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1107 "event filter", parse_filter),

--- 27 unchanged lines hidden (view full) ---

1135 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1136 "print counts with custom separator"),
1137 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1138 "monitor event in cgroup name only", parse_cgroups),
1139 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1140 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1141 OPT_INTEGER(0, "log-fd", &output_fd,
1142 "log output to fd, instead of stderr"),
1143 OPT_STRING(0, "pre", &pre_cmd, "command",
1144 "command to run prior to the measured command"),
1145 OPT_STRING(0, "post", &post_cmd, "command",
1146 "command to run after to the measured command"),
1117 OPT_END()
1118 };
1119 const char * const stat_usage[] = {
1120 "perf stat [<options>] [<command>]",
1121 NULL
1122 };
1123 struct perf_evsel *pos;
1124 int status = -ENOMEM, run_idx;

--- 108 unchanged lines hidden (view full) ---

1233 signal(SIGABRT, skip_signal);
1234
1235 status = 0;
1236 for (run_idx = 0; run_idx < run_count; run_idx++) {
1237 if (run_count != 1 && verbose)
1238 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
1239 run_idx + 1);
1240
1147 OPT_END()
1148 };
1149 const char * const stat_usage[] = {
1150 "perf stat [<options>] [<command>]",
1151 NULL
1152 };
1153 struct perf_evsel *pos;
1154 int status = -ENOMEM, run_idx;

--- 108 unchanged lines hidden (view full) ---

1263 signal(SIGABRT, skip_signal);
1264
1265 status = 0;
1266 for (run_idx = 0; run_idx < run_count; run_idx++) {
1267 if (run_count != 1 && verbose)
1268 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
1269 run_idx + 1);
1270
1241 if (sync_run)
1242 sync();
1243
1244 status = run_perf_stat(argc, argv);
1245 }
1246
1247 if (status != -1)
1248 print_stat(argc, argv);
1249out_free_fd:
1250 list_for_each_entry(pos, &evsel_list->entries, node)
1251 perf_evsel__free_stat_priv(pos);
1252 perf_evlist__delete_maps(evsel_list);
1253out:
1254 perf_evlist__delete(evsel_list);
1255 return status;
1256}
1271 status = run_perf_stat(argc, argv);
1272 }
1273
1274 if (status != -1)
1275 print_stat(argc, argv);
1276out_free_fd:
1277 list_for_each_entry(pos, &evsel_list->entries, node)
1278 perf_evsel__free_stat_priv(pos);
1279 perf_evlist__delete_maps(evsel_list);
1280out:
1281 perf_evlist__delete(evsel_list);
1282 return status;
1283}