Skip to content

Commit a1bf230

Browse files
namhyungacmel
authored andcommitted
perf stat: Take cgroups into account for shadow stats
As of now it doesn't consider cgroups when collecting shadow stats and metrics so counter values from different cgroups will be saved in a same slot. This resulted in incorrect numbers when those cgroups have different workloads. For example, let's look at the scenario below: cgroups A and C runs same workload which burns a cpu while cgroup B runs a light workload. $ perf stat -a -e cycles,instructions --for-each-cgroup A,B,C sleep 1 Performance counter stats for 'system wide': 3,958,116,522 cycles A 6,722,650,929 instructions A # 2.53 insn per cycle 1,132,741 cycles B 571,743 instructions B # 0.00 insn per cycle 4,007,799,935 cycles C 6,793,181,523 instructions C # 2.56 insn per cycle 1.001050869 seconds time elapsed When I run 'perf stat' with single workload, it usually shows IPC around 1.7. We can verify it (6,722,650,929.0 / 3,958,116,522 = 1.698) for cgroup A. But in this case, since cgroups are ignored, cycles are averaged so it used the lower value for IPC calculation and resulted in around 2.5. avg cycle: (3958116522 + 1132741 + 4007799935) / 3 = 2655683066 IPC (A) : 6722650929 / 2655683066 = 2.531 IPC (B) : 571743 / 2655683066 = 0.0002 IPC (C) : 6793181523 / 2655683066 = 2.557 We can simply compare cgroup pointers in the evsel and it'll be NULL when cgroups are not specified. With this patch, I can see correct numbers like below: $ perf stat -a -e cycles,instructions --for-each-cgroup A,B,C sleep 1 Performance counter stats for 'system wide': 4,171,051,687 cycles A 7,219,793,922 instructions A # 1.73 insn per cycle 1,051,189 cycles B 583,102 instructions B # 0.55 insn per cycle 4,171,124,710 cycles C 7,192,944,580 instructions C # 1.72 insn per cycle 1.007909814 seconds time elapsed Signed-off-by: Namhyung Kim <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Jin Yao <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 3ff1e71 commit a1bf230

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

tools/perf/util/stat-shadow.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "evlist.h"
99
#include "expr.h"
1010
#include "metricgroup.h"
11+
#include "cgroup.h"
1112
#include <linux/zalloc.h>
1213

1314
/*
@@ -28,6 +29,7 @@ struct saved_value {
2829
enum stat_type type;
2930
int ctx;
3031
int cpu;
32+
struct cgroup *cgrp;
3133
struct runtime_stat *stat;
3234
struct stats stats;
3335
u64 metric_total;
@@ -57,6 +59,9 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
5759
if (a->ctx != b->ctx)
5860
return a->ctx - b->ctx;
5961

62+
if (a->cgrp != b->cgrp)
63+
return (char *)a->cgrp < (char *)b->cgrp ? -1 : +1;
64+
6065
if (a->evsel == NULL && b->evsel == NULL) {
6166
if (a->stat == b->stat)
6267
return 0;
@@ -100,7 +105,8 @@ static struct saved_value *saved_value_lookup(struct evsel *evsel,
100105
bool create,
101106
enum stat_type type,
102107
int ctx,
103-
struct runtime_stat *st)
108+
struct runtime_stat *st,
109+
struct cgroup *cgrp)
104110
{
105111
struct rblist *rblist;
106112
struct rb_node *nd;
@@ -110,6 +116,7 @@ static struct saved_value *saved_value_lookup(struct evsel *evsel,
110116
.type = type,
111117
.ctx = ctx,
112118
.stat = st,
119+
.cgrp = cgrp,
113120
};
114121

115122
rblist = &st->value_list;
@@ -197,6 +204,7 @@ void perf_stat__reset_shadow_per_stat(struct runtime_stat *st)
197204

198205
struct runtime_stat_data {
199206
int ctx;
207+
struct cgroup *cgrp;
200208
};
201209

202210
static void update_runtime_stat(struct runtime_stat *st,
@@ -205,7 +213,7 @@ static void update_runtime_stat(struct runtime_stat *st,
205213
struct runtime_stat_data *rsd)
206214
{
207215
struct saved_value *v = saved_value_lookup(NULL, cpu, true, type,
208-
rsd->ctx, st);
216+
rsd->ctx, st, rsd->cgrp);
209217

210218
if (v)
211219
update_stats(&v->stats, count);
@@ -223,6 +231,7 @@ void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
223231
struct saved_value *v;
224232
struct runtime_stat_data rsd = {
225233
.ctx = evsel_context(counter),
234+
.cgrp = counter->cgrp,
226235
};
227236

228237
count *= counter->scale;
@@ -290,13 +299,14 @@ void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
290299
update_runtime_stat(st, STAT_APERF, cpu, count, &rsd);
291300

292301
if (counter->collect_stat) {
293-
v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st);
302+
v = saved_value_lookup(counter, cpu, true, STAT_NONE, 0, st,
303+
rsd.cgrp);
294304
update_stats(&v->stats, count);
295305
if (counter->metric_leader)
296306
v->metric_total += count;
297307
} else if (counter->metric_leader) {
298308
v = saved_value_lookup(counter->metric_leader,
299-
cpu, true, STAT_NONE, 0, st);
309+
cpu, true, STAT_NONE, 0, st, rsd.cgrp);
300310
v->metric_total += count;
301311
v->metric_other++;
302312
}
@@ -438,7 +448,7 @@ static double runtime_stat_avg(struct runtime_stat *st,
438448
{
439449
struct saved_value *v;
440450

441-
v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st);
451+
v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st, rsd->cgrp);
442452
if (!v)
443453
return 0.0;
444454

@@ -451,7 +461,7 @@ static double runtime_stat_n(struct runtime_stat *st,
451461
{
452462
struct saved_value *v;
453463

454-
v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st);
464+
v = saved_value_lookup(NULL, cpu, false, type, rsd->ctx, st, rsd->cgrp);
455465
if (!v)
456466
return 0.0;
457467

@@ -805,7 +815,8 @@ static int prepare_metric(struct evsel **metric_events,
805815
scale = 1e-9;
806816
} else {
807817
v = saved_value_lookup(metric_events[i], cpu, false,
808-
STAT_NONE, 0, st);
818+
STAT_NONE, 0, st,
819+
metric_events[i]->cgrp);
809820
if (!v)
810821
break;
811822
stats = &v->stats;
@@ -933,6 +944,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
933944
const char *color = NULL;
934945
struct runtime_stat_data rsd = {
935946
.ctx = evsel_context(evsel),
947+
.cgrp = evsel->cgrp,
936948
};
937949
struct metric_event *me;
938950
int num = 1;

0 commit comments

Comments
 (0)