^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "color.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "counts.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "stat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "top.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "thread_map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "cpumap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "string2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "cgroup.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <api/fs/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define CNTR_NOT_SUPPORTED "<not supported>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define CNTR_NOT_COUNTED "<not counted>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void print_running(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u64 run, u64 ena)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (config->csv_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) fprintf(config->output, "%s%" PRIu64 "%s%.2f",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) run,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ena ? 100.0 * run / ena : 100.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) } else if (run != ena) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) fprintf(config->output, " (%.2f%%)", 100.0 * run / ena);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void print_noise_pct(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) double total, double avg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) double pct = rel_stddev_stats(total, avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) else if (pct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) fprintf(config->output, " ( +-%6.2f%% )", pct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void print_noise(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct evsel *evsel, double avg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct perf_stat_evsel *ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (config->run_count == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ps = evsel->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void print_cgroup(struct perf_stat_config *config, struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (nr_cgroups) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const char *cgrp_name = evsel->cgrp ? evsel->cgrp->name : "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) fprintf(config->output, "%s%s", config->csv_sep, cgrp_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void aggr_printout(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct evsel *evsel, int id, int nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) switch (config->aggr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case AGGR_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) fprintf(config->output, "S%d-D%d-C%*d%s%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) cpu_map__id_to_socket(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cpu_map__id_to_die(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) config->csv_output ? 0 : -8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) cpu_map__id_to_cpu(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) config->csv_output ? 0 : 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case AGGR_DIE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) fprintf(config->output, "S%d-D%*d%s%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) cpu_map__id_to_socket(id << 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) config->csv_output ? 0 : -8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) cpu_map__id_to_die(id << 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) config->csv_output ? 0 : 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case AGGR_SOCKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) fprintf(config->output, "S%*d%s%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) config->csv_output ? 0 : -5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) config->csv_output ? 0 : 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case AGGR_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) fprintf(config->output, "N%*d%s%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) config->csv_output ? 0 : -5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) config->csv_sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) config->csv_output ? 0 : 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case AGGR_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (evsel->percore && !config->percore_show_thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) fprintf(config->output, "S%d-D%d-C%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) cpu_map__id_to_socket(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) cpu_map__id_to_die(id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) config->csv_output ? 0 : -3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) cpu_map__id_to_cpu(id), config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } else if (id > -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) fprintf(config->output, "CPU%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) config->csv_output ? 0 : -7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) evsel__cpus(evsel)->map[id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case AGGR_THREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fprintf(config->output, "%*s-%*d%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) config->csv_output ? 0 : 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) perf_thread_map__comm(evsel->core.threads, id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) config->csv_output ? 0 : -8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) perf_thread_map__pid(evsel->core.threads, id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case AGGR_GLOBAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case AGGR_UNSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct outstate {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) FILE *fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bool newline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int nfields;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int id, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define METRIC_LEN 35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void new_line_std(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) os->newline = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static void do_new_line_std(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct outstate *os)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fputc('\n', os->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) fputs(os->prefix, os->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) aggr_printout(config, os->evsel, os->id, os->nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (config->aggr_mode == AGGR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fprintf(os->fh, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fprintf(os->fh, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void print_metric_std(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void *ctx, const char *color, const char *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) const char *unit, double val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) FILE *out = os->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) bool newline = os->newline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) os->newline = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (unit == NULL || fmt == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) fprintf(out, "%-*s", METRIC_LEN, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (newline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) do_new_line_std(config, os);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) n = fprintf(out, " # ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) n += color_fprintf(out, color, fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) n += fprintf(out, fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static void new_line_csv(struct perf_stat_config *config, void *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) fputc('\n', os->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (os->prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) aggr_printout(config, os->evsel, os->id, os->nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for (i = 0; i < os->nfields; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) fputs(config->csv_sep, os->fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) void *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) const char *color __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) const char *fmt, const char *unit, double val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) FILE *out = os->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) char buf[64], *vals, *ends;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (unit == NULL || fmt == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) snprintf(buf, sizeof(buf), fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ends = vals = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) while (isdigit(*ends) || *ends == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ends++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *ends = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, skip_spaces(unit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Filter out some columns that don't work well in metrics only mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static bool valid_only_metric(const char *unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (strstr(unit, "/sec") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) strstr(unit, "CPUs utilized"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static const char *fixunit(char *buf, struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) const char *unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!strncmp(unit, "of all", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) snprintf(buf, 1024, "%s %s", evsel__name(evsel),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void print_metric_only(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) void *ctx, const char *color, const char *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) const char *unit, double val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) FILE *out = os->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) char buf[1024], str[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned mlen = config->metric_only_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!valid_only_metric(unit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unit = fixunit(buf, os->evsel, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (mlen < strlen(unit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mlen = strlen(unit) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) color_snprintf(str, sizeof(str), color ?: "", fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) fprintf(out, "%*s ", mlen, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) void *ctx, const char *color __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) const char *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) const char *unit, double val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) FILE *out = os->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) char buf[64], *vals, *ends;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) char tbuf[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!valid_only_metric(unit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) unit = fixunit(tbuf, os->evsel, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) snprintf(buf, sizeof buf, fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ends = vals = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) while (isdigit(*ends) || *ends == '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ends++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *ends = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) fprintf(out, "%s%s", vals, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static void new_line_metric(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void *ctx __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void print_metric_header(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) void *ctx, const char *color __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const char *fmt __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) const char *unit, double val __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct outstate *os = ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) char tbuf[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!valid_only_metric(unit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unit = fixunit(tbuf, os->evsel, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) fprintf(os->fh, "%s%s", unit, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) fprintf(os->fh, "%*s ", config->metric_only_len, unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int first_shadow_cpu(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct evsel *evsel, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct evlist *evlist = evsel->evlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (config->aggr_mode == AGGR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (!config->aggr_get_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (i = 0; i < evsel__nr_cpus(evsel); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int cpu2 = evsel__cpus(evsel)->map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (config->aggr_get_id(config, evlist->core.cpus, cpu2) == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return cpu2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static void abs_printout(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int id, int nr, struct evsel *evsel, double avg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) double sc = evsel->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) const char *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (config->csv_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (config->big_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) aggr_printout(config, evsel, id, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) fprintf(output, fmt, avg, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (evsel->unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) fprintf(output, "%-*s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) config->csv_output ? 0 : config->unit_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) evsel->unit, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) fprintf(output, "%-*s", config->csv_output ? 0 : 25, evsel__name(evsel));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) print_cgroup(config, evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static bool is_mixed_hw_group(struct evsel *counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct evlist *evlist = counter->evlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) u32 pmu_type = counter->core.attr.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct evsel *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (counter->core.nr_members < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) evlist__for_each_entry(evlist, pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* software events can be part of any hardware group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (pos->core.attr.type == PERF_TYPE_SOFTWARE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (pmu_type == PERF_TYPE_SOFTWARE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) pmu_type = pos->core.attr.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (pmu_type != pos->core.attr.type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static void printout(struct perf_stat_config *config, int id, int nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct evsel *counter, double uval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) char *prefix, u64 run, u64 ena, double noise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct runtime_stat *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct perf_stat_output_ctx out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct outstate os = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .fh = config->output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) .prefix = prefix ? prefix : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .id = id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .nr = nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .evsel = counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) print_metric_t pm = print_metric_std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) new_line_t nl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (config->metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) nl = new_line_metric;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) pm = print_metric_only_csv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) pm = print_metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) nl = new_line_std;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (config->csv_output && !config->metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int aggr_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) [AGGR_GLOBAL] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) [AGGR_THREAD] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) [AGGR_NONE] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) [AGGR_SOCKET] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) [AGGR_DIE] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) [AGGR_CORE] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pm = print_metric_csv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) nl = new_line_csv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) os.nfields = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) os.nfields += aggr_fields[config->aggr_mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (counter->cgrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) os.nfields++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (config->metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) pm(config, &os, NULL, "", "", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) aggr_printout(config, counter, id, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) fprintf(config->output, "%*s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) config->csv_output ? 0 : 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (counter->supported) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) config->print_free_counters_hint = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (is_mixed_hw_group(counter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) config->print_mixed_hw_group_error = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) fprintf(config->output, "%-*s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) config->csv_output ? 0 : config->unit_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) counter->unit, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fprintf(config->output, "%*s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) config->csv_output ? 0 : -25, evsel__name(counter));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) print_cgroup(config, counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (!config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pm(config, &os, NULL, NULL, "", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) print_noise(config, counter, noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) print_running(config, run, ena);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) pm(config, &os, NULL, NULL, "", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (!config->metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) abs_printout(config, id, nr, counter, uval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) out.print_metric = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) out.new_line = nl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) out.ctx = &os;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) out.force_header = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (config->csv_output && !config->metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) print_noise(config, counter, noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) print_running(config, run, ena);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) perf_stat__print_shadow_stats(config, counter, uval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) first_shadow_cpu(config, counter, id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) &out, &config->metric_events, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!config->csv_output && !config->metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) print_noise(config, counter, noise);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) print_running(config, run, ena);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static void aggr_update_shadow(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct evlist *evlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int cpu, s2, id, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct evsel *counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) for (s = 0; s < config->aggr_map->nr; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) id = config->aggr_map->map[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) s2 = config->aggr_get_id(config, evlist->core.cpus, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (s2 != id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) val += perf_counts(counter->counts, cpu, 0)->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) perf_stat__update_shadow_stats(counter, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) first_shadow_cpu(config, counter, id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) static void uniquify_event_name(struct evsel *counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) char *new_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) char *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (counter->uniquified_name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) strlen(counter->pmu_name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) config = strchr(counter->name, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (config) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (asprintf(&new_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) "%s%s", counter->pmu_name, config) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) free(counter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) counter->name = new_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (asprintf(&new_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) "%s [%s]", counter->name, counter->pmu_name) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) free(counter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) counter->name = new_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) counter->uniquified_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static void collect_all_aliases(struct perf_stat_config *config, struct evsel *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) bool first),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct evlist *evlist = counter->evlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct evsel *alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) alias = list_prepare_entry(counter, &(evlist->core.entries), core.node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) list_for_each_entry_continue (alias, &evlist->core.entries, core.node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* Merge events with the same name, etc. but on different PMUs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!strcmp(evsel__name(alias), evsel__name(counter)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) alias->scale == counter->scale &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) alias->cgrp == counter->cgrp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) !strcmp(alias->unit, counter->unit) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) evsel__is_clock(alias) == evsel__is_clock(counter) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) strcmp(alias->pmu_name, counter->pmu_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) alias->merged_stat = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) cb(config, alias, data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) bool first),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (counter->merged_stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) cb(config, counter, data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (config->no_merge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) uniquify_event_name(counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) else if (counter->auto_merge_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) collect_all_aliases(config, counter, cb, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct aggr_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) u64 ena, run, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static void aggr_cb(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct evsel *counter, void *data, bool first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct aggr_data *ad = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int cpu, s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct perf_counts_values *counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) s2 = config->aggr_get_id(config, evsel__cpus(counter), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (s2 != ad->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ad->nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) counts = perf_counts(counter->counts, cpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * When any result is bad, make them all to give
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * consistent output in interval mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (counts->ena == 0 || counts->run == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) counter->counts->scaled == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ad->ena = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ad->run = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ad->val += counts->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ad->ena += counts->ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ad->run += counts->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static void print_counter_aggrdata(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct evsel *counter, int s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) char *prefix, bool metric_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) bool *first, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct aggr_data ad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) u64 ena, run, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int id, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) double uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ad.id = id = config->aggr_map->map[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ad.val = ad.ena = ad.run = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ad.nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!collect_data(config, counter, aggr_cb, &ad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) nr = ad.nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ena = ad.ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) run = ad.run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) val = ad.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (*first && metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) *first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) aggr_printout(config, counter, id, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (prefix && !metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) uval = val * counter->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) printout(config, cpu != -1 ? cpu : id, nr, counter, uval, prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) run, ena, 1.0, &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) fputc('\n', output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static void print_aggr(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) bool metric_only = config->metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct evsel *counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) bool first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (!config->aggr_map || !config->aggr_get_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) aggr_update_shadow(config, evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * With metric_only everything is on a single line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * Without each counter has its own line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) for (s = 0; s < config->aggr_map->nr; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (prefix && metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) print_counter_aggrdata(config, counter, s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) prefix, metric_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) &first, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) fputc('\n', output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static int cmp_val(const void *a, const void *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return ((struct perf_aggr_thread_value *)b)->val -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ((struct perf_aggr_thread_value *)a)->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static struct perf_aggr_thread_value *sort_aggr_thread(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct evsel *counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int nthreads, int ncpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int *ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct target *_target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int cpu, thread, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) double uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct perf_aggr_thread_value *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) for (thread = 0; thread < nthreads; thread++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) u64 ena = 0, run = 0, val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) for (cpu = 0; cpu < ncpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) val += perf_counts(counter->counts, cpu, thread)->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ena += perf_counts(counter->counts, cpu, thread)->ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) run += perf_counts(counter->counts, cpu, thread)->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) uval = val * counter->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * Skip value 0 when enabling --per-thread globally,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * otherwise too many 0 output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (uval == 0.0 && target__has_per_thread(_target))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) buf[i].counter = counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) buf[i].id = thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) buf[i].uval = uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) buf[i].val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) buf[i].run = run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) buf[i].ena = ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) *ret = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static void print_aggr_thread(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) struct target *_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct evsel *counter, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) int nthreads = perf_thread_map__nr(counter->core.threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int ncpus = perf_cpu_map__nr(counter->core.cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) int thread, sorted_threads, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct perf_aggr_thread_value *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) perror("cannot sort aggr thread");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) for (thread = 0; thread < sorted_threads; thread++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) id = buf[thread].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (config->stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) printout(config, id, 0, buf[thread].counter, buf[thread].uval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) prefix, buf[thread].run, buf[thread].ena, 1.0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) &config->stats[id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) printout(config, id, 0, buf[thread].counter, buf[thread].uval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) prefix, buf[thread].run, buf[thread].ena, 1.0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) fputc('\n', output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) free(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct caggr_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) double avg, avg_enabled, avg_running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct evsel *counter, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) bool first __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) struct caggr_data *cd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct perf_stat_evsel *ps = counter->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) cd->avg += avg_stats(&ps->res_stats[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) cd->avg_enabled += avg_stats(&ps->res_stats[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) cd->avg_running += avg_stats(&ps->res_stats[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * Print out the results of a single counter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * aggregated counts in system-wide mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static void print_counter_aggr(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct evsel *counter, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) bool metric_only = config->metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) double uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct caggr_data cd = { .avg = 0.0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (!collect_data(config, counter, counter_aggr_cb, &cd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (prefix && !metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) uval = cd.avg * counter->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) cd.avg, &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) fprintf(output, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static void counter_cb(struct perf_stat_config *config __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct evsel *counter, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) bool first __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct aggr_data *ad = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * Print out the results of a single counter:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * does not use aggregated count in system-wide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static void print_counter(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct evsel *counter, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) u64 ena, run, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) double uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct aggr_data ad = { .cpu = cpu };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (!collect_data(config, counter, counter_cb, &ad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) val = ad.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) ena = ad.ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) run = ad.run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) uval = val * counter->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) fputc('\n', output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static void print_no_aggr_metric(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int nrcpus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct evsel *counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) u64 ena, run, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) double uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) nrcpus = evlist->core.cpus->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) for (cpu = 0; cpu < nrcpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) fputs(prefix, config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) aggr_printout(config, counter, cpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) val = perf_counts(counter->counts, cpu, 0)->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) ena = perf_counts(counter->counts, cpu, 0)->ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) run = perf_counts(counter->counts, cpu, 0)->run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) uval = val * counter->scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) fputc('\n', config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static int aggr_header_lens[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) [AGGR_CORE] = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) [AGGR_DIE] = 18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) [AGGR_SOCKET] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) [AGGR_NONE] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) [AGGR_THREAD] = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) [AGGR_GLOBAL] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static const char *aggr_header_csv[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) [AGGR_CORE] = "core,cpus,",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) [AGGR_DIE] = "die,cpus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) [AGGR_SOCKET] = "socket,cpus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) [AGGR_NONE] = "cpu,",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) [AGGR_THREAD] = "comm-pid,",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) [AGGR_GLOBAL] = ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static void print_metric_headers(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) const char *prefix, bool no_indent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct perf_stat_output_ctx out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct evsel *counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct outstate os = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .fh = config->output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) fprintf(config->output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (!config->csv_output && !no_indent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) fprintf(config->output, "%*s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) aggr_header_lens[config->aggr_mode], "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (config->csv_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (config->interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) fputs("time,", config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) fputs(aggr_header_csv[config->aggr_mode], config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* Print metrics headers only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) os.evsel = counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) out.ctx = &os;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) out.print_metric = print_metric_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) out.new_line = new_line_metric;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) out.force_header = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) perf_stat__print_shadow_stats(config, counter, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) &out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) &config->metric_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) &rt_stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) fputc('\n', config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static void print_interval(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) char *prefix, struct timespec *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) bool metric_only = config->metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unsigned int unit_width = config->unit_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int num_print_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (config->interval_clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) puts(CONSOLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) switch (config->aggr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) case AGGR_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) fprintf(output, "# time node cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case AGGR_SOCKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) fprintf(output, "# time socket cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) case AGGR_DIE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) fprintf(output, "# time die cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case AGGR_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) fprintf(output, "# time core cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case AGGR_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) fprintf(output, "# time CPU ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) case AGGR_THREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) fprintf(output, "# time comm-pid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) case AGGR_GLOBAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) fprintf(output, "# time");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (!metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) fprintf(output, " counts %*s events\n", unit_width, "unit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case AGGR_UNSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if ((num_print_interval == 0 || config->interval_clear) && metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) print_metric_headers(config, evlist, " ", true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (++num_print_interval == 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) num_print_interval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static void print_header(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct target *_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!config->csv_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) fprintf(output, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) fprintf(output, " Performance counter stats for ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (_target->system_wide)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) fprintf(output, "\'system wide");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) else if (_target->cpu_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) fprintf(output, "\'CPU(s) %s", _target->cpu_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) else if (!target__has_task(_target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) fprintf(output, "\'%s", argv ? argv[0] : "pipe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) for (i = 1; argv && (i < argc); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) fprintf(output, " %s", argv[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) } else if (_target->pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) fprintf(output, "process id \'%s", _target->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) fprintf(output, "thread id \'%s", _target->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) fprintf(output, "\'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (config->run_count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) fprintf(output, " (%d runs)", config->run_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) fprintf(output, ":\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static int get_precision(double num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (num > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return lround(ceil(-log10(num)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static void print_table(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) FILE *output, int precision, double avg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) char tmp[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) int idx, indent = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) scnprintf(tmp, 64, " %17.*f", precision, avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) while (tmp[indent] == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) indent++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) for (idx = 0; idx < config->run_count; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) fprintf(output, " %17.*f (%+.*f) ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) precision, run, precision, run - avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) for (h = 0; h < n; h++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) fprintf(output, "#");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) fprintf(output, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) fprintf(output, "\n%*s# Final result:\n", indent, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static double timeval2double(struct timeval *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static void print_footer(struct perf_stat_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (!config->null_run)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) fprintf(output, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (config->run_count == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) fprintf(output, " %17.9f seconds time elapsed", avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (config->ru_display) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) double ru_utime = timeval2double(&config->ru_data.ru_utime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) double ru_stime = timeval2double(&config->ru_data.ru_stime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) fprintf(output, "\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) fprintf(output, " %17.9f seconds user\n", ru_utime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) fprintf(output, " %17.9f seconds sys\n", ru_stime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * Display at most 2 more significant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * digits than the stddev inaccuracy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) int precision = get_precision(sd) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (config->walltime_run_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) print_table(config, output, precision, avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) fprintf(output, " %17.*f +- %.*f seconds time elapsed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) precision, avg, precision, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) print_noise_pct(config, sd, avg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) fprintf(output, "\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if (config->print_free_counters_hint && sysctl__nmi_watchdog_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) fprintf(output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) "Some events weren't counted. Try disabling the NMI watchdog:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) " echo 0 > /proc/sys/kernel/nmi_watchdog\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) " perf stat ...\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) " echo 1 > /proc/sys/kernel/nmi_watchdog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (config->print_mixed_hw_group_error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) fprintf(output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) "The events in group usually have to be from "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) "the same PMU. Try reorganizing the group.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) static void print_percore_thread(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct evsel *counter, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) int s, s2, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) for (int i = 0; i < evsel__nr_cpus(counter); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) s2 = config->aggr_get_id(config, evsel__cpus(counter), i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) for (s = 0; s < config->aggr_map->nr; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) id = config->aggr_map->map[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (s2 == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) print_counter_aggrdata(config, counter, s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) prefix, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) &first, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static void print_percore(struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) struct evsel *counter, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) bool metric_only = config->metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) FILE *output = config->output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) int s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (!config->aggr_map || !config->aggr_get_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (config->percore_show_thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return print_percore_thread(config, counter, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) for (s = 0; s < config->aggr_map->nr; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (prefix && metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) fprintf(output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) print_counter_aggrdata(config, counter, s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) prefix, metric_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) &first, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) fputc('\n', output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) perf_evlist__print_counters(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct perf_stat_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct target *_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct timespec *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) bool metric_only = config->metric_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) int interval = config->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct evsel *counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) char buf[64], *prefix = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) print_interval(config, evlist, prefix = buf, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) print_header(config, _target, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (metric_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static int num_print_iv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (num_print_iv == 0 && !interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) print_metric_headers(config, evlist, prefix, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (num_print_iv++ == 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) num_print_iv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) if (config->aggr_mode == AGGR_GLOBAL && prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) fprintf(config->output, "%s", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) switch (config->aggr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) case AGGR_CORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) case AGGR_DIE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) case AGGR_SOCKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) case AGGR_NODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) print_aggr(config, evlist, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) case AGGR_THREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) print_aggr_thread(config, _target, counter, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case AGGR_GLOBAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) print_counter_aggr(config, counter, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) fputc('\n', config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) case AGGR_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (metric_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) print_no_aggr_metric(config, evlist, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) evlist__for_each_entry(evlist, counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (counter->percore)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) print_percore(config, counter, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) print_counter(config, counter, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) case AGGR_UNSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (!interval && !config->csv_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) print_footer(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) fflush(config->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }