]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - tools/perf/util/stat.c
perf stat: Fix transaction lenght metrics
[mirror_ubuntu-bionic-kernel.git] / tools / perf / util / stat.c
CommitLineData
0007ecea 1#include <math.h>
0007ecea 2#include "stat.h"
24e34f68 3#include "evlist.h"
e2f56da1 4#include "evsel.h"
24e34f68 5#include "thread_map.h"
0007ecea
XG
6
7void update_stats(struct stats *stats, u64 val)
8{
9 double delta;
10
11 stats->n++;
12 delta = val - stats->mean;
13 stats->mean += delta / stats->n;
14 stats->M2 += delta*(val - stats->mean);
ffe4f3c0
DA
15
16 if (val > stats->max)
17 stats->max = val;
18
19 if (val < stats->min)
20 stats->min = val;
0007ecea
XG
21}
22
23double avg_stats(struct stats *stats)
24{
25 return stats->mean;
26}
27
28/*
29 * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
30 *
31 * (\Sum n_i^2) - ((\Sum n_i)^2)/n
32 * s^2 = -------------------------------
33 * n - 1
34 *
35 * http://en.wikipedia.org/wiki/Stddev
36 *
37 * The std dev of the mean is related to the std dev by:
38 *
39 * s
40 * s_mean = -------
41 * sqrt(n)
42 *
43 */
44double stddev_stats(struct stats *stats)
45{
46 double variance, variance_mean;
47
45528f7c 48 if (stats->n < 2)
0007ecea
XG
49 return 0.0;
50
51 variance = stats->M2 / (stats->n - 1);
52 variance_mean = variance / stats->n;
53
54 return sqrt(variance_mean);
55}
56
57double rel_stddev_stats(double stddev, double avg)
58{
59 double pct = 0.0;
60
61 if (avg)
62 pct = 100.0 * stddev/avg;
63
64 return pct;
65}
e2f56da1
JO
66
67bool __perf_evsel_stat__is(struct perf_evsel *evsel,
68 enum perf_stat_evsel_id id)
69{
70 struct perf_stat *ps = evsel->priv;
71
72 return ps->id == id;
73}
74
75#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
76static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
4c358d5c
JO
77 ID(NONE, x),
78 ID(CYCLES_IN_TX, cpu/cycles-t/),
79 ID(TRANSACTION_START, cpu/tx-start/),
80 ID(ELISION_START, cpu/el-start/),
81 ID(CYCLES_IN_TX_CP, cpu/cycles-ct/),
e2f56da1
JO
82};
83#undef ID
84
85void perf_stat_evsel_id_init(struct perf_evsel *evsel)
86{
87 struct perf_stat *ps = evsel->priv;
88 int i;
89
90 /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
91
92 for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
93 if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
94 ps->id = i;
95 break;
96 }
97 }
98}
a9a3a4d9 99
a6fa0038 100struct perf_counts *perf_counts__new(int ncpus, int nthreads)
9df38e82 101{
a8e02324 102 struct perf_counts *counts = zalloc(sizeof(*counts));
9df38e82 103
a8e02324 104 if (counts) {
57b28915 105 struct xyarray *values;
a8e02324 106
57b28915
JO
107 values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
108 if (!values) {
a8e02324
JO
109 free(counts);
110 return NULL;
111 }
112
57b28915 113 counts->values = values;
a8e02324
JO
114 }
115
116 return counts;
9df38e82
JO
117}
118
119void perf_counts__delete(struct perf_counts *counts)
120{
a8e02324 121 if (counts) {
57b28915 122 xyarray__delete(counts->values);
a8e02324
JO
123 free(counts);
124 }
9df38e82
JO
125}
126
a8e02324 127static void perf_counts__reset(struct perf_counts *counts)
9df38e82 128{
57b28915 129 xyarray__reset(counts->values);
9df38e82
JO
130}
131
a8e02324 132void perf_evsel__reset_counts(struct perf_evsel *evsel)
a9a3a4d9 133{
a8e02324 134 perf_counts__reset(evsel->counts);
a9a3a4d9
JO
135}
136
a6fa0038 137int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
a9a3a4d9 138{
a6fa0038 139 evsel->counts = perf_counts__new(ncpus, nthreads);
a9a3a4d9
JO
140 return evsel->counts != NULL ? 0 : -ENOMEM;
141}
142
143void perf_evsel__free_counts(struct perf_evsel *evsel)
144{
9df38e82
JO
145 perf_counts__delete(evsel->counts);
146 evsel->counts = NULL;
a9a3a4d9 147}
9689edfa
JO
148
149void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
150{
151 int i;
152 struct perf_stat *ps = evsel->priv;
153
154 for (i = 0; i < 3; i++)
155 init_stats(&ps->res_stats[i]);
156
157 perf_stat_evsel_id_init(evsel);
158}
159
160int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
161{
162 evsel->priv = zalloc(sizeof(struct perf_stat));
163 if (evsel->priv == NULL)
164 return -ENOMEM;
165 perf_evsel__reset_stat_priv(evsel);
166 return 0;
167}
168
169void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
170{
171 zfree(&evsel->priv);
172}
a939512d
JO
173
174int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
175 int ncpus, int nthreads)
176{
177 struct perf_counts *counts;
178
179 counts = perf_counts__new(ncpus, nthreads);
180 if (counts)
181 evsel->prev_raw_counts = counts;
182
183 return counts ? 0 : -ENOMEM;
184}
185
186void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
187{
188 perf_counts__delete(evsel->prev_raw_counts);
189 evsel->prev_raw_counts = NULL;
190}
24e34f68 191
a7d0a102
JO
192int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
193{
194 int ncpus = perf_evsel__nr_cpus(evsel);
195 int nthreads = thread_map__nr(evsel->threads);
196
197 if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
198 perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
199 (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
200 return -ENOMEM;
201
202 return 0;
203}
204
24e34f68
JO
205int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
206{
207 struct perf_evsel *evsel;
24e34f68
JO
208
209 evlist__for_each(evlist, evsel) {
a7d0a102 210 if (perf_evsel__alloc_stats(evsel, alloc_raw))
24e34f68
JO
211 goto out_free;
212 }
213
214 return 0;
215
216out_free:
217 perf_evlist__free_stats(evlist);
218 return -1;
219}
220
221void perf_evlist__free_stats(struct perf_evlist *evlist)
222{
223 struct perf_evsel *evsel;
224
225 evlist__for_each(evlist, evsel) {
226 perf_evsel__free_stat_priv(evsel);
227 perf_evsel__free_counts(evsel);
228 perf_evsel__free_prev_raw_counts(evsel);
229 }
230}
231
232void perf_evlist__reset_stats(struct perf_evlist *evlist)
233{
234 struct perf_evsel *evsel;
235
236 evlist__for_each(evlist, evsel) {
237 perf_evsel__reset_stat_priv(evsel);
238 perf_evsel__reset_counts(evsel);
239 }
240}