Commit | Line | Data |
---|---|---|
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 | |
7 | void 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 | ||
23 | double 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 | */ | |
44 | double 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 | ||
57 | double 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 | |
67 | bool __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 | |
76 | static 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 | ||
85 | void 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 | 100 | struct 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 | ||
119 | void 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 | 127 | static void perf_counts__reset(struct perf_counts *counts) |
9df38e82 | 128 | { |
57b28915 | 129 | xyarray__reset(counts->values); |
9df38e82 JO |
130 | } |
131 | ||
a8e02324 | 132 | void perf_evsel__reset_counts(struct perf_evsel *evsel) |
a9a3a4d9 | 133 | { |
a8e02324 | 134 | perf_counts__reset(evsel->counts); |
a9a3a4d9 JO |
135 | } |
136 | ||
a6fa0038 | 137 | int 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 | ||
143 | void 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 | |
149 | void 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 | ||
160 | int 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 | ||
169 | void perf_evsel__free_stat_priv(struct perf_evsel *evsel) | |
170 | { | |
171 | zfree(&evsel->priv); | |
172 | } | |
a939512d JO |
173 | |
174 | int 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 | ||
186 | void 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 |
192 | int 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 |
205 | int 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 | ||
216 | out_free: | |
217 | perf_evlist__free_stats(evlist); | |
218 | return -1; | |
219 | } | |
220 | ||
221 | void 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 | ||
232 | void 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 | } |