stat.c 4.6 KB
Newer Older
1 2
#include <math.h>
#include "stat.h"
3
#include "evlist.h"
4
#include "evsel.h"
5
#include "thread_map.h"
6 7 8 9 10 11 12 13 14

void update_stats(struct stats *stats, u64 val)
{
	double delta;

	stats->n++;
	delta = val - stats->mean;
	stats->mean += delta / stats->n;
	stats->M2 += delta*(val - stats->mean);
D
David Ahern 已提交
15 16 17 18 19 20

	if (val > stats->max)
		stats->max = val;

	if (val < stats->min)
		stats->min = val;
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
}

double avg_stats(struct stats *stats)
{
	return stats->mean;
}

/*
 * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
 *
 *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
 * s^2 = -------------------------------
 *                  n - 1
 *
 * http://en.wikipedia.org/wiki/Stddev
 *
 * The std dev of the mean is related to the std dev by:
 *
 *             s
 * s_mean = -------
 *          sqrt(n)
 *
 */
double stddev_stats(struct stats *stats)
{
	double variance, variance_mean;

48
	if (stats->n < 2)
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
		return 0.0;

	variance = stats->M2 / (stats->n - 1);
	variance_mean = variance / stats->n;

	return sqrt(variance_mean);
}

double rel_stddev_stats(double stddev, double avg)
{
	double pct = 0.0;

	if (avg)
		pct = 100.0 * stddev/avg;

	return pct;
}
66 67 68 69 70 71 72 73 74 75 76

bool __perf_evsel_stat__is(struct perf_evsel *evsel,
			   enum perf_stat_evsel_id id)
{
	struct perf_stat *ps = evsel->priv;

	return ps->id == id;
}

#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
77 78 79 80 81
	ID(NONE,		x),
	ID(CYCLES_IN_TX,	cpu/cycles-t/),
	ID(TRANSACTION_START,	cpu/tx-start/),
	ID(ELISION_START,	cpu/el-start/),
	ID(CYCLES_IN_TX_CP,	cpu/cycles-ct/),
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
};
#undef ID

void perf_stat_evsel_id_init(struct perf_evsel *evsel)
{
	struct perf_stat *ps = evsel->priv;
	int i;

	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */

	for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
		if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
			ps->id = i;
			break;
		}
	}
}
99

100
struct perf_counts *perf_counts__new(int ncpus, int nthreads)
101
{
102
	struct perf_counts *counts = zalloc(sizeof(*counts));
103

104
	if (counts) {
105
		struct xyarray *values;
106

107 108
		values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
		if (!values) {
109 110 111 112
			free(counts);
			return NULL;
		}

113
		counts->values = values;
114 115 116
	}

	return counts;
117 118 119 120
}

void perf_counts__delete(struct perf_counts *counts)
{
121
	if (counts) {
122
		xyarray__delete(counts->values);
123 124
		free(counts);
	}
125 126
}

127
static void perf_counts__reset(struct perf_counts *counts)
128
{
129
	xyarray__reset(counts->values);
130 131
}

132
void perf_evsel__reset_counts(struct perf_evsel *evsel)
133
{
134
	perf_counts__reset(evsel->counts);
135 136
}

137
int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
138
{
139
	evsel->counts = perf_counts__new(ncpus, nthreads);
140 141 142 143 144
	return evsel->counts != NULL ? 0 : -ENOMEM;
}

void perf_evsel__free_counts(struct perf_evsel *evsel)
{
145 146
	perf_counts__delete(evsel->counts);
	evsel->counts = NULL;
147
}
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
{
	int i;
	struct perf_stat *ps = evsel->priv;

	for (i = 0; i < 3; i++)
		init_stats(&ps->res_stats[i]);

	perf_stat_evsel_id_init(evsel);
}

int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
{
	evsel->priv = zalloc(sizeof(struct perf_stat));
	if (evsel->priv == NULL)
		return -ENOMEM;
	perf_evsel__reset_stat_priv(evsel);
	return 0;
}

void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
{
	zfree(&evsel->priv);
}
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
				      int ncpus, int nthreads)
{
	struct perf_counts *counts;

	counts = perf_counts__new(ncpus, nthreads);
	if (counts)
		evsel->prev_raw_counts = counts;

	return counts ? 0 : -ENOMEM;
}

void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
{
	perf_counts__delete(evsel->prev_raw_counts);
	evsel->prev_raw_counts = NULL;
}
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
{
	struct perf_evsel *evsel;
	int nthreads = thread_map__nr(evlist->threads);

	evlist__for_each(evlist, evsel) {
		int ncpus = perf_evsel__nr_cpus(evsel);

		if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
		    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
			goto out_free;
	}

	return 0;

out_free:
	perf_evlist__free_stats(evlist);
	return -1;
}

void perf_evlist__free_stats(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel;

	evlist__for_each(evlist, evsel) {
		perf_evsel__free_stat_priv(evsel);
		perf_evsel__free_counts(evsel);
		perf_evsel__free_prev_raw_counts(evsel);
	}
}

void perf_evlist__reset_stats(struct perf_evlist *evlist)
{
	struct perf_evsel *evsel;

	evlist__for_each(evlist, evsel) {
		perf_evsel__reset_stat_priv(evsel);
		perf_evsel__reset_counts(evsel);
	}
}