Linux Perf
stat.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <inttypes.h>
4 #include <math.h>
5 #include "stat.h"
6 #include "evlist.h"
7 #include "evsel.h"
8 #include "thread_map.h"
9 
10 void update_stats(struct stats *stats, u64 val)
11 {
12  double delta;
13 
14  stats->n++;
15  delta = val - stats->mean;
16  stats->mean += delta / stats->n;
17  stats->M2 += delta*(val - stats->mean);
18 
19  if (val > stats->max)
20  stats->max = val;
21 
22  if (val < stats->min)
23  stats->min = val;
24 }
25 
26 double avg_stats(struct stats *stats)
27 {
28  return stats->mean;
29 }
30 
31 /*
32  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
33  *
34  * (\Sum n_i^2) - ((\Sum n_i)^2)/n
35  * s^2 = -------------------------------
36  * n - 1
37  *
38  * http://en.wikipedia.org/wiki/Stddev
39  *
40  * The std dev of the mean is related to the std dev by:
41  *
42  * s
43  * s_mean = -------
44  * sqrt(n)
45  *
46  */
47 double stddev_stats(struct stats *stats)
48 {
49  double variance, variance_mean;
50 
51  if (stats->n < 2)
52  return 0.0;
53 
54  variance = stats->M2 / (stats->n - 1);
55  variance_mean = variance / stats->n;
56 
57  return sqrt(variance_mean);
58 }
59 
60 double rel_stddev_stats(double stddev, double avg)
61 {
62  double pct = 0.0;
63 
64  if (avg)
65  pct = 100.0 * stddev/avg;
66 
67  return pct;
68 }
69 
70 bool __perf_evsel_stat__is(struct perf_evsel *evsel,
71  enum perf_stat_evsel_id id)
72 {
73  struct perf_stat_evsel *ps = evsel->stats;
74 
75  return ps->id == id;
76 }
77 
78 #define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
79 static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
80  ID(NONE, x),
81  ID(CYCLES_IN_TX, cpu/cycles-t/),
82  ID(TRANSACTION_START, cpu/tx-start/),
83  ID(ELISION_START, cpu/el-start/),
84  ID(CYCLES_IN_TX_CP, cpu/cycles-ct/),
85  ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
86  ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
87  ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
88  ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
89  ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
90  ID(SMI_NUM, msr/smi/),
91  ID(APERF, msr/aperf/),
92 };
93 #undef ID
94 
95 static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
96 {
97  struct perf_stat_evsel *ps = evsel->stats;
98  int i;
99 
100  /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
101 
102  for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
103  if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
104  ps->id = i;
105  break;
106  }
107  }
108 }
109 
110 static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
111 {
112  int i;
113  struct perf_stat_evsel *ps = evsel->stats;
114 
115  for (i = 0; i < 3; i++)
116  init_stats(&ps->res_stats[i]);
117 
119 }
120 
121 static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
122 {
123  evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
124  if (evsel->stats == NULL)
125  return -ENOMEM;
127  return 0;
128 }
129 
130 static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
131 {
132  struct perf_stat_evsel *ps = evsel->stats;
133 
134  if (ps)
135  free(ps->group_data);
136  zfree(&evsel->stats);
137 }
138 
140  int ncpus, int nthreads)
141 {
142  struct perf_counts *counts;
143 
144  counts = perf_counts__new(ncpus, nthreads);
145  if (counts)
146  evsel->prev_raw_counts = counts;
147 
148  return counts ? 0 : -ENOMEM;
149 }
150 
152 {
154  evsel->prev_raw_counts = NULL;
155 }
156 
157 static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
158 {
159  int ncpus = perf_evsel__nr_cpus(evsel);
160  int nthreads = thread_map__nr(evsel->threads);
161 
162  if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
163  perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
164  (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
165  return -ENOMEM;
166 
167  return 0;
168 }
169 
170 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
171 {
172  struct perf_evsel *evsel;
173 
174  evlist__for_each_entry(evlist, evsel) {
175  if (perf_evsel__alloc_stats(evsel, alloc_raw))
176  goto out_free;
177  }
178 
179  return 0;
180 
181 out_free:
182  perf_evlist__free_stats(evlist);
183  return -1;
184 }
185 
187 {
188  struct perf_evsel *evsel;
189 
190  evlist__for_each_entry(evlist, evsel) {
194  }
195 }
196 
198 {
199  struct perf_evsel *evsel;
200 
201  evlist__for_each_entry(evlist, evsel) {
204  }
205 }
206 
207 static void zero_per_pkg(struct perf_evsel *counter)
208 {
209  if (counter->per_pkg_mask)
210  memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
211 }
212 
213 static int check_per_pkg(struct perf_evsel *counter,
214  struct perf_counts_values *vals, int cpu, bool *skip)
215 {
216  unsigned long *mask = counter->per_pkg_mask;
217  struct cpu_map *cpus = perf_evsel__cpus(counter);
218  int s;
219 
220  *skip = false;
221 
222  if (!counter->per_pkg)
223  return 0;
224 
225  if (cpu_map__empty(cpus))
226  return 0;
227 
228  if (!mask) {
229  mask = zalloc(MAX_NR_CPUS);
230  if (!mask)
231  return -ENOMEM;
232 
233  counter->per_pkg_mask = mask;
234  }
235 
236  /*
237  * we do not consider an event that has not run as a good
238  * instance to mark a package as used (skip=1). Otherwise
239  * we may run into a situation where the first CPU in a package
240  * is not running anything, yet the second is, and this function
241  * would mark the package as used after the first CPU and would
242  * not read the values from the second CPU.
243  */
244  if (!(vals->run && vals->ena))
245  return 0;
246 
247  s = cpu_map__get_socket(cpus, cpu, NULL);
248  if (s < 0)
249  return -1;
250 
251  *skip = test_and_set_bit(s, mask) == 1;
252  return 0;
253 }
254 
255 static int
257  int cpu, int thread,
258  struct perf_counts_values *count)
259 {
260  struct perf_counts_values *aggr = &evsel->counts->aggr;
261  static struct perf_counts_values zero;
262  bool skip = false;
263 
264  if (check_per_pkg(evsel, count, cpu, &skip)) {
265  pr_err("failed to read per-pkg counter\n");
266  return -1;
267  }
268 
269  if (skip)
270  count = &zero;
271 
272  switch (config->aggr_mode) {
273  case AGGR_THREAD:
274  case AGGR_CORE:
275  case AGGR_SOCKET:
276  case AGGR_NONE:
277  if (!evsel->snapshot)
278  perf_evsel__compute_deltas(evsel, cpu, thread, count);
279  perf_counts_values__scale(count, config->scale, NULL);
280  if (config->aggr_mode == AGGR_NONE)
281  perf_stat__update_shadow_stats(evsel, count->val, cpu,
282  &rt_stat);
283  if (config->aggr_mode == AGGR_THREAD) {
284  if (config->stats)
286  count->val, 0, &config->stats[thread]);
287  else
289  count->val, 0, &rt_stat);
290  }
291  break;
292  case AGGR_GLOBAL:
293  aggr->val += count->val;
294  if (config->scale) {
295  aggr->ena += count->ena;
296  aggr->run += count->run;
297  }
298  case AGGR_UNSET:
299  default:
300  break;
301  }
302 
303  return 0;
304 }
305 
307  struct perf_evsel *counter)
308 {
309  int nthreads = thread_map__nr(counter->threads);
310  int ncpus = perf_evsel__nr_cpus(counter);
311  int cpu, thread;
312 
313  if (counter->system_wide)
314  nthreads = 1;
315 
316  for (thread = 0; thread < nthreads; thread++) {
317  for (cpu = 0; cpu < ncpus; cpu++) {
318  if (process_counter_values(config, counter, cpu, thread,
319  perf_counts(counter->counts, cpu, thread)))
320  return -1;
321  }
322  }
323 
324  return 0;
325 }
326 
328  struct perf_evsel *counter)
329 {
330  struct perf_counts_values *aggr = &counter->counts->aggr;
331  struct perf_stat_evsel *ps = counter->stats;
332  u64 *count = counter->counts->aggr.values;
333  int i, ret;
334 
335  aggr->val = aggr->ena = aggr->run = 0;
336 
337  /*
338  * We calculate counter's data every interval,
339  * and the display code shows ps->res_stats
340  * avg value. We need to zero the stats for
341  * interval mode, otherwise overall avg running
342  * averages will be shown for each interval.
343  */
344  if (config->interval)
345  init_stats(ps->res_stats);
346 
347  if (counter->per_pkg)
348  zero_per_pkg(counter);
349 
350  ret = process_counter_maps(config, counter);
351  if (ret)
352  return ret;
353 
354  if (config->aggr_mode != AGGR_GLOBAL)
355  return 0;
356 
357  if (!counter->snapshot)
358  perf_evsel__compute_deltas(counter, -1, -1, aggr);
359  perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
360 
361  for (i = 0; i < 3; i++)
362  update_stats(&ps->res_stats[i], count[i]);
363 
364  if (verbose > 0) {
365  fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
366  perf_evsel__name(counter), count[0], count[1], count[2]);
367  }
368 
369  /*
370  * Save the full runtime - to allow normalization during printout:
371  */
372  perf_stat__update_shadow_stats(counter, *count, 0, &rt_stat);
373 
374  return 0;
375 }
376 
377 int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
378  union perf_event *event,
379  struct perf_session *session)
380 {
381  struct perf_counts_values count;
382  struct stat_event *st = &event->stat;
383  struct perf_evsel *counter;
384 
385  count.val = st->val;
386  count.ena = st->ena;
387  count.run = st->run;
388 
389  counter = perf_evlist__id2evsel(session->evlist, st->id);
390  if (!counter) {
391  pr_err("Failed to resolve counter for stat event.\n");
392  return -EINVAL;
393  }
394 
395  *perf_counts(counter->counts, st->cpu, st->thread) = count;
396  counter->supported = true;
397  return 0;
398 }
399 
400 size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
401 {
402  struct stat_event *st = (struct stat_event *) event;
403  size_t ret;
404 
405  ret = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
406  st->id, st->cpu, st->thread);
407  ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
408  st->val, st->ena, st->run);
409 
410  return ret;
411 }
412 
414 {
415  struct stat_round_event *rd = (struct stat_round_event *)event;
416  size_t ret;
417 
418  ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
419  rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
420 
421  return ret;
422 }
423 
425 {
426  struct perf_stat_config sc;
427  size_t ret;
428 
430 
431  ret = fprintf(fp, "\n");
432  ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
433  ret += fprintf(fp, "... scale %d\n", sc.scale);
434  ret += fprintf(fp, "... interval %u\n", sc.interval);
435 
436  return ret;
437 }
def avg(total, n)
Definition: Util.py:19
double avg_stats(struct stats *stats)
Definition: stat.c:26
struct perf_evlist * evlist
Definition: session.h:25
FILE * output
Definition: stat.h:90
void perf_evlist__free_stats(struct perf_evlist *evlist)
Definition: stat.c:186
void perf_counts_values__scale(struct perf_counts_values *count, bool scale, s8 *pscaled)
Definition: evsel.c:1288
static int process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count)
Definition: stat.c:256
enum aggr_mode aggr_mode
Definition: stat.h:88
static void skip(int size)
static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
Definition: stat.c:95
static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
Definition: stat.c:157
bool system_wide
Definition: evsel.h:124
bool snapshot
Definition: evsel.h:119
u32 thread
Definition: event.h:587
#define config
size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
Definition: stat.c:400
Definition: cpumap.h:12
struct stat_config_event stat_config
Definition: event.h:649
double stddev_stats(struct stats *stats)
Definition: stat.c:47
struct runtime_stat rt_stat
Definition: stat-shadow.c:21
#define pr_err(fmt,...)
Definition: json.h:21
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
#define min(x, y)
Definition: jevents.h:15
bool per_pkg
Definition: evsel.h:126
static void init_stats(struct stats *stats)
Definition: stat.h:103
bool supported
Definition: evsel.h:120
u64 min
Definition: stat.h:12
static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
Definition: stat.c:130
#define ID(id, name)
Definition: stat.c:78
Definition: thread.h:18
static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
Definition: stat.c:151
u64 val
Definition: event.h:591
bool __perf_evsel_stat__is(struct perf_evsel *evsel, enum perf_stat_evsel_id id)
Definition: stat.c:70
struct perf_evlist * evlist
Definition: evsel.h:92
Definition: tool.h:44
void update_stats(struct stats *stats, u64 val)
Definition: stat.c:10
static struct perf_session * session
Definition: builtin-lock.c:34
void perf_evsel__reset_counts(struct perf_evsel *evsel)
Definition: counts.c:40
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
perf_stat_evsel_id
Definition: stat.h:15
Definition: stat.h:41
static bool cpu_map__empty(const struct cpu_map *map)
Definition: cpumap.h:58
static unsigned int nthreads
Definition: futex-hash.c:31
double M2
Definition: stat.h:11
u64 run
Definition: event.h:593
static struct cpu_map * perf_evsel__cpus(struct perf_evsel *evsel)
Definition: evsel.h:175
struct perf_counts_values aggr
Definition: counts.h:21
struct perf_counts * prev_raw_counts
Definition: evsel.h:99
size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
Definition: stat.c:424
static struct perf_tool tool
Definition: builtin-diff.c:362
static void zero_per_pkg(struct perf_evsel *counter)
Definition: stat.c:207
void perf_evlist__reset_stats(struct perf_evlist *evlist)
Definition: stat.c:197
bool scale
Definition: stat.h:89
list cpus
Definition: stat-cpi.py:7
double rel_stddev_stats(double stddev, double avg)
Definition: stat.c:60
u64 values[3]
Definition: counts.h:14
struct perf_evsel * perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
Definition: evlist.c:589
static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
Definition: stat.c:121
static int process_counter_maps(struct perf_stat_config *config, struct perf_evsel *counter)
Definition: stat.c:306
#define event
struct perf_counts * counts
Definition: evsel.h:98
static const char * id_str[PERF_STAT_EVSEL_ID__MAX]
Definition: stat.c:79
struct stats res_stats[3]
Definition: stat.h:32
s8 scaled
Definition: counts.h:20
struct thread_map * threads
Definition: evsel.h:114
#define zfree(ptr)
Definition: util.h:25
const char * perf_evsel__name(struct perf_evsel *evsel)
Definition: evsel.c:577
double mean
Definition: stat.h:11
int perf_stat_process_counter(struct perf_stat_config *config, struct perf_evsel *counter)
Definition: stat.c:327
double n
Definition: stat.h:11
static int thread_map__nr(struct thread_map *threads)
Definition: thread_map.h:41
u64 * group_data
Definition: stat.h:34
void perf_evsel__free_counts(struct perf_evsel *evsel)
Definition: counts.c:51
void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, int cpu, struct runtime_stat *st)
Definition: stat-shadow.c:208
size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
Definition: stat.c:413
void perf_counts__delete(struct perf_counts *counts)
Definition: counts.c:27
u64 start
Definition: hists_common.c:25
struct runtime_stat * stats
Definition: stat.h:94
int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
Definition: counts.c:45
struct perf_counts * perf_counts__new(int ncpus, int nthreads)
Definition: counts.c:8
u64 max
Definition: stat.h:12
int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
Definition: stat.c:170
u64 id
Definition: event.h:585
int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session)
Definition: stat.c:377
unsigned long * per_pkg_mask
Definition: evsel.h:135
Definition: stat.h:10
u32 cpu
Definition: event.h:586
static unsigned int ncpus
Definition: futex-wake.c:45
unsigned int interval
Definition: stat.h:91
void free(void *)
static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
Definition: stat.c:110
#define MAX_NR_CPUS
Definition: perf.h:27
static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
Definition: stat.c:139
static int perf_evsel__nr_cpus(struct perf_evsel *evsel)
Definition: evsel.h:180
void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count)
Definition: evsel.c:1267
static struct perf_counts_values * perf_counts(struct perf_counts *counts, int cpu, int thread)
Definition: counts.h:27
int verbose
Definition: jevents.c:53
struct perf_stat_evsel * stats
Definition: evsel.h:107
enum perf_stat_evsel_id id
Definition: stat.h:33
int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
Definition: cpumap.c:320
Definition: stat.h:38
void perf_event__read_stat_config(struct perf_stat_config *config, struct stat_config_event *event)
Definition: event.c:1210
void static void * zalloc(size_t size)
Definition: util.h:20
u64 ena
Definition: event.h:592
static int check_per_pkg(struct perf_evsel *counter, struct perf_counts_values *vals, int cpu, bool *skip)
Definition: stat.c:213