Skip to content

Commit 9aba0ad

Browse files
captain5050acmel
authored andcommitted
perf expr: Add source_count for aggregating events
Events like uncore_imc/cas_count_read/ on Skylake open multiple events and then aggregate in the metric leader. To determine the average value per event the number of these events is needed. Add a source_count function that returns this value by counting the number of events with the given metric leader. For most events the value is 1 but for uncore_imc/cas_count_read/ it can yield values like 6. Add a generic test, but manually tested with a test metric that uses the function. Signed-off-by: Ian Rogers <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: John Garry <[email protected]> Cc: Kajol Jain <[email protected]> Cc: Kan Liang <[email protected]> Cc: Madhavan Srinivasan <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Paul A . Clarke <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Riccardo Mancini <[email protected]> Cc: Song Liu <[email protected]> Cc: Wan Jiabing <[email protected]> Cc: Yury Norov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 1e7ab82 commit 9aba0ad

File tree

8 files changed

+66
-12
lines changed

8 files changed

+66
-12
lines changed

tools/perf/tests/expr.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,18 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
171171
TEST_ASSERT_VAL("#num_packages", expr__parse(&num_packages, ctx, "#num_packages") == 0);
172172
TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages);
173173

174+
/*
175+
* Source count returns the number of events aggregating in a leader
176+
* event including the leader. Check parsing yields an id.
177+
*/
178+
expr__ctx_clear(ctx);
179+
TEST_ASSERT_VAL("source count",
180+
expr__find_ids("source_count(EVENT1)",
181+
NULL, ctx) == 0);
182+
TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1);
183+
TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, "EVENT1",
184+
(void **)&val_ptr));
185+
174186
expr__ctx_free(ctx);
175187

176188
return 0;

tools/perf/util/evsel.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,3 +3037,15 @@ void evsel__set_leader(struct evsel *evsel, struct evsel *leader)
30373037
{
30383038
evsel->core.leader = &leader->core;
30393039
}
3040+
3041+
int evsel__source_count(const struct evsel *evsel)
3042+
{
3043+
struct evsel *pos;
3044+
int count = 0;
3045+
3046+
evlist__for_each_entry(evsel->evlist, pos) {
3047+
if (pos->metric_leader == evsel)
3048+
count++;
3049+
}
3050+
return count;
3051+
}

tools/perf/util/evsel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ struct evsel *evsel__leader(struct evsel *evsel);
489489
bool evsel__has_leader(struct evsel *evsel, struct evsel *leader);
490490
bool evsel__is_leader(struct evsel *evsel);
491491
void evsel__set_leader(struct evsel *evsel, struct evsel *leader);
492+
int evsel__source_count(const struct evsel *evsel);
492493

493494
/*
494495
* Macro to swap the bit-field postition and size.

tools/perf/util/expr.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ extern int expr_debug;
2323

2424
struct expr_id_data {
2525
union {
26-
double val;
26+
struct {
27+
double val;
28+
int source_count;
29+
} val;
2730
struct {
2831
double val;
2932
const char *metric_name;
@@ -140,6 +143,13 @@ int expr__add_id(struct expr_parse_ctx *ctx, const char *id)
140143

141144
/* Caller must make sure id is allocated */
142145
int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val)
146+
{
147+
return expr__add_id_val_source_count(ctx, id, val, /*source_count=*/1);
148+
}
149+
150+
/* Caller must make sure id is allocated */
151+
int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id,
152+
double val, int source_count)
143153
{
144154
struct expr_id_data *data_ptr = NULL, *old_data = NULL;
145155
char *old_key = NULL;
@@ -148,7 +158,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val)
148158
data_ptr = malloc(sizeof(*data_ptr));
149159
if (!data_ptr)
150160
return -ENOMEM;
151-
data_ptr->val = val;
161+
data_ptr->val.val = val;
162+
data_ptr->val.source_count = source_count;
152163
data_ptr->kind = EXPR_ID_DATA__VALUE;
153164

154165
ret = hashmap__set(ctx->ids, id, data_ptr,
@@ -244,7 +255,7 @@ int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id,
244255

245256
switch (data->kind) {
246257
case EXPR_ID_DATA__VALUE:
247-
pr_debug2("lookup(%s): val %f\n", id, data->val);
258+
pr_debug2("lookup(%s): val %f\n", id, data->val.val);
248259
break;
249260
case EXPR_ID_DATA__REF:
250261
pr_debug2("lookup(%s): ref metric name %s\n", id,
@@ -255,7 +266,7 @@ int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id,
255266
pr_debug("%s failed to count\n", id);
256267
return -1;
257268
}
258-
pr_debug("processing metric: %s EXIT: %f\n", id, data->val);
269+
pr_debug("processing metric: %s EXIT: %f\n", id, data->ref.val);
259270
break;
260271
case EXPR_ID_DATA__REF_VALUE:
261272
pr_debug2("lookup(%s): ref val %f metric name %s\n", id,
@@ -370,11 +381,17 @@ int expr__find_ids(const char *expr, const char *one,
370381
double expr_id_data__value(const struct expr_id_data *data)
371382
{
372383
if (data->kind == EXPR_ID_DATA__VALUE)
373-
return data->val;
384+
return data->val.val;
374385
assert(data->kind == EXPR_ID_DATA__REF_VALUE);
375386
return data->ref.val;
376387
}
377388

389+
double expr_id_data__source_count(const struct expr_id_data *data)
390+
{
391+
assert(data->kind == EXPR_ID_DATA__VALUE);
392+
return data->val.source_count;
393+
}
394+
378395
double expr__get_literal(const char *literal)
379396
{
380397
static struct cpu_topology *topology;

tools/perf/util/expr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ void expr__ctx_free(struct expr_parse_ctx *ctx);
4040
void expr__del_id(struct expr_parse_ctx *ctx, const char *id);
4141
int expr__add_id(struct expr_parse_ctx *ctx, const char *id);
4242
int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val);
43+
int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id,
44+
double val, int source_count);
4345
int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref);
4446
int expr__get_id(struct expr_parse_ctx *ctx, const char *id,
4547
struct expr_id_data **data);
@@ -55,6 +57,7 @@ int expr__find_ids(const char *expr, const char *one,
5557
struct expr_parse_ctx *ids);
5658

5759
double expr_id_data__value(const struct expr_id_data *data);
60+
double expr_id_data__source_count(const struct expr_id_data *data);
5861
double expr__get_literal(const char *literal);
5962

6063
#endif

tools/perf/util/expr.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ max { return MAX; }
107107
min { return MIN; }
108108
if { return IF; }
109109
else { return ELSE; }
110+
source_count { return SOURCE_COUNT; }
110111
{literal} { return literal(yyscanner); }
111112
{number} { return value(yyscanner); }
112113
{symbol} { return str(yyscanner, ID, sctx->runtime); }

tools/perf/util/expr.y

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
} ids;
3838
}
3939

40-
%token ID NUMBER MIN MAX IF ELSE LITERAL D_RATIO EXPR_ERROR
40+
%token ID NUMBER MIN MAX IF ELSE LITERAL D_RATIO SOURCE_COUNT EXPR_ERROR
4141
%left MIN MAX IF
4242
%left '|'
4343
%left '^'
@@ -84,7 +84,7 @@ static struct ids union_expr(struct ids ids1, struct ids ids2)
8484
}
8585

8686
static struct ids handle_id(struct expr_parse_ctx *ctx, char *id,
87-
bool compute_ids)
87+
bool compute_ids, bool source_count)
8888
{
8989
struct ids result;
9090

@@ -96,9 +96,11 @@ static struct ids handle_id(struct expr_parse_ctx *ctx, char *id,
9696
struct expr_id_data *data;
9797

9898
result.val = NAN;
99-
if (expr__resolve_id(ctx, id, &data) == 0)
100-
result.val = expr_id_data__value(data);
101-
99+
if (expr__resolve_id(ctx, id, &data) == 0) {
100+
result.val = source_count
101+
? expr_id_data__source_count(data)
102+
: expr_id_data__value(data);
103+
}
102104
result.ids = NULL;
103105
free(id);
104106
} else {
@@ -201,7 +203,8 @@ expr: NUMBER
201203
$$.val = $1;
202204
$$.ids = NULL;
203205
}
204-
| ID { $$ = handle_id(ctx, $1, compute_ids); }
206+
| ID { $$ = handle_id(ctx, $1, compute_ids, /*source_count=*/false); }
207+
| SOURCE_COUNT '(' ID ')' { $$ = handle_id(ctx, $3, compute_ids, /*source_count=*/true); }
205208
| expr '|' expr { BINARY_LONG_OP($$, |, $1, $3); }
206209
| expr '&' expr { BINARY_LONG_OP($$, &, $1, $3); }
207210
| expr '^' expr { BINARY_LONG_OP($$, ^, $1, $3); }

tools/perf/util/stat-shadow.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,10 +829,12 @@ static int prepare_metric(struct evsel **metric_events,
829829
struct saved_value *v;
830830
struct stats *stats;
831831
u64 metric_total = 0;
832+
int source_count;
832833

833834
if (!strcmp(metric_events[i]->name, "duration_time")) {
834835
stats = &walltime_nsecs_stats;
835836
scale = 1e-9;
837+
source_count = 1;
836838
} else {
837839
v = saved_value_lookup(metric_events[i], cpu, false,
838840
STAT_NONE, 0, st,
@@ -841,6 +843,7 @@ static int prepare_metric(struct evsel **metric_events,
841843
break;
842844
stats = &v->stats;
843845
scale = 1.0;
846+
source_count = evsel__source_count(metric_events[i]);
844847

845848
if (v->metric_other)
846849
metric_total = v->metric_total;
@@ -849,7 +852,9 @@ static int prepare_metric(struct evsel **metric_events,
849852
if (!n)
850853
return -ENOMEM;
851854

852-
expr__add_id_val(pctx, n, metric_total ? : avg_stats(stats) * scale);
855+
expr__add_id_val_source_count(pctx, n,
856+
metric_total ? : avg_stats(stats) * scale,
857+
source_count);
853858
}
854859

855860
for (j = 0; metric_refs && metric_refs[j].metric_name; j++) {

0 commit comments

Comments
 (0)