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} |