kernel_optimize_test/tools/perf/tests/parse-metric.c

305 lines
7.7 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <string.h>
#include <perf/cpumap.h>
#include <perf/evlist.h>
#include "metricgroup.h"
#include "tests.h"
#include "pmu-events/pmu-events.h"
#include "evlist.h"
#include "rblist.h"
#include "debug.h"
#include "expr.h"
#include "stat.h"
#include <perf/cpumap.h>
#include <perf/evlist.h>
static struct pmu_event pme_test[] = {
{
.metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
.metric_name = "IPC",
},
perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-03 05:47:41 +08:00
{
.metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
"( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
.metric_name = "Frontend_Bound_SMT",
},
{
.metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
.metric_name = "dcache_miss_cpi",
},
{
.metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
.metric_name = "icache_miss_cycles",
},
{
.metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
.metric_name = "cache_miss_cycles",
},
{
.metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
.metric_name = "DCache_L2_All_Hits",
},
{
.metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
"l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
.metric_name = "DCache_L2_All_Miss",
},
{
.metric_expr = "dcache_l2_all_hits + dcache_l2_all_miss",
.metric_name = "DCache_L2_All",
},
{
.metric_expr = "d_ratio(dcache_l2_all_hits, dcache_l2_all)",
.metric_name = "DCache_L2_Hits",
},
{
.metric_expr = "d_ratio(dcache_l2_all_miss, dcache_l2_all)",
.metric_name = "DCache_L2_Misses",
},
perf metric: Add recursion check when processing nested metrics Keeping the stack of nested metrics via 'struct expr_id' objects and checking if we are in recursion via already processed metric. The stack is implemented as static array within the struct egroup with 100 entries, which should be enough nesting depth for any metric we have or plan to have at the moment. Adding test that simulates the recursion and checks we can detect it. Committer notes: Bumped RECURSION_ID_MAX to 1000 as per Jiri's reply to Paul Clark on the patch series e-mail discussion. Fixed these: tests/parse-metric.c:308:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, ^ util/metricgroup.c:924:28: error: missing field 'parent' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:28: error: missing field 'cnt' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200719181320.785305-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-20 02:13:16 +08:00
{
.metric_expr = "ipc + m2",
.metric_name = "M1",
},
{
.metric_expr = "ipc + m1",
.metric_name = "M2",
},
{
.metric_expr = "1/m3",
.metric_name = "M3",
}
};
static struct pmu_events_map map = {
.cpuid = "test",
.version = "1",
.type = "core",
.table = pme_test,
};
struct value {
const char *event;
u64 val;
};
static u64 find_value(const char *name, struct value *values)
{
struct value *v = values;
while (v->event) {
if (!strcmp(name, v->event))
return v->val;
v++;
};
return 0;
}
static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist,
struct value *vals)
{
struct evsel *evsel;
u64 count;
evlist__for_each_entry(evlist, evsel) {
count = find_value(evsel->name, vals);
perf_stat__update_shadow_stats(evsel, count, 0, st);
}
}
static double compute_single(struct rblist *metric_events, struct evlist *evlist,
struct runtime_stat *st)
{
struct evsel *evsel = evlist__first(evlist);
struct metric_event *me;
me = metricgroup__lookup(metric_events, evsel, false);
if (me != NULL) {
struct metric_expr *mexp;
mexp = list_first_entry(&me->head, struct metric_expr, nd);
return test_generic_metric(mexp, 0, st);
}
return 0.;
}
static int compute_metric(const char *name, struct value *vals, double *ratio)
{
struct rblist metric_events = {
.nr_entries = 0,
};
struct perf_cpu_map *cpus;
struct runtime_stat st;
struct evlist *evlist;
int err;
/*
* We need to prepare evlist for stat mode running on CPU 0
* because that's where all the stats are going to be created.
*/
evlist = evlist__new();
if (!evlist)
return -ENOMEM;
cpus = perf_cpu_map__new("0");
if (!cpus)
return -ENOMEM;
perf_evlist__set_maps(&evlist->core, cpus, NULL);
/* Parse the metric into metric_events list. */
err = metricgroup__parse_groups_test(evlist, &map, name,
false, false,
&metric_events);
perf metric: Add recursion check when processing nested metrics Keeping the stack of nested metrics via 'struct expr_id' objects and checking if we are in recursion via already processed metric. The stack is implemented as static array within the struct egroup with 100 entries, which should be enough nesting depth for any metric we have or plan to have at the moment. Adding test that simulates the recursion and checks we can detect it. Committer notes: Bumped RECURSION_ID_MAX to 1000 as per Jiri's reply to Paul Clark on the patch series e-mail discussion. Fixed these: tests/parse-metric.c:308:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, ^ util/metricgroup.c:924:28: error: missing field 'parent' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:28: error: missing field 'cnt' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200719181320.785305-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-20 02:13:16 +08:00
if (err)
return err;
if (perf_evlist__alloc_stats(evlist, false))
return -1;
/* Load the runtime stats with given numbers for events. */
runtime_stat__init(&st);
load_runtime_stat(&st, evlist, vals);
/* And execute the metric */
*ratio = compute_single(&metric_events, evlist, &st);
/* ... clenup. */
metricgroup__rblist_exit(&metric_events);
runtime_stat__exit(&st);
perf_evlist__free_stats(evlist);
perf_cpu_map__put(cpus);
evlist__delete(evlist);
return 0;
}
static int test_ipc(void)
{
double ratio;
struct value vals[] = {
{ .event = "inst_retired.any", .val = 300 },
{ .event = "cpu_clk_unhalted.thread", .val = 200 },
{ .event = NULL, },
};
TEST_ASSERT_VAL("failed to compute metric",
compute_metric("IPC", vals, &ratio) == 0);
TEST_ASSERT_VAL("IPC failed, wrong ratio",
ratio == 1.5);
return 0;
}
perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-03 05:47:41 +08:00
static int test_frontend(void)
{
double ratio;
struct value vals[] = {
{ .event = "idq_uops_not_delivered.core", .val = 300 },
{ .event = "cpu_clk_unhalted.thread", .val = 200 },
{ .event = "cpu_clk_unhalted.one_thread_active", .val = 400 },
{ .event = "cpu_clk_unhalted.ref_xclk", .val = 600 },
{ .event = NULL, },
};
TEST_ASSERT_VAL("failed to compute metric",
compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0);
TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio",
ratio == 0.45);
return 0;
}
static int test_cache_miss_cycles(void)
{
double ratio;
struct value vals[] = {
{ .event = "l1d-loads-misses", .val = 300 },
{ .event = "l1i-loads-misses", .val = 200 },
{ .event = "inst_retired.any", .val = 400 },
{ .event = NULL, },
};
TEST_ASSERT_VAL("failed to compute metric",
compute_metric("cache_miss_cycles", vals, &ratio) == 0);
TEST_ASSERT_VAL("cache_miss_cycles failed, wrong ratio",
ratio == 1.25);
return 0;
}
/*
* DCache_L2_All_Hits = l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hi
* DCache_L2_All_Miss = max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) +
* l2_rqsts.pf_miss + l2_rqsts.rfo_miss
* DCache_L2_All = dcache_l2_all_hits + dcache_l2_all_miss
* DCache_L2_Hits = d_ratio(dcache_l2_all_hits, dcache_l2_all)
* DCache_L2_Misses = d_ratio(dcache_l2_all_miss, dcache_l2_all)
*
* l2_rqsts.demand_data_rd_hit = 100
* l2_rqsts.pf_hit = 200
* l2_rqsts.rfo_hi = 300
* l2_rqsts.all_demand_data_rd = 400
* l2_rqsts.pf_miss = 500
* l2_rqsts.rfo_miss = 600
*
* DCache_L2_All_Hits = 600
* DCache_L2_All_Miss = MAX(400 - 100, 0) + 500 + 600 = 1400
* DCache_L2_All = 600 + 1400 = 2000
* DCache_L2_Hits = 600 / 2000 = 0.3
* DCache_L2_Misses = 1400 / 2000 = 0.7
*/
static int test_dcache_l2(void)
{
double ratio;
struct value vals[] = {
{ .event = "l2_rqsts.demand_data_rd_hit", .val = 100 },
{ .event = "l2_rqsts.pf_hit", .val = 200 },
{ .event = "l2_rqsts.rfo_hit", .val = 300 },
{ .event = "l2_rqsts.all_demand_data_rd", .val = 400 },
{ .event = "l2_rqsts.pf_miss", .val = 500 },
{ .event = "l2_rqsts.rfo_miss", .val = 600 },
{ .event = NULL, },
};
TEST_ASSERT_VAL("failed to compute metric",
compute_metric("DCache_L2_Hits", vals, &ratio) == 0);
TEST_ASSERT_VAL("DCache_L2_Hits failed, wrong ratio",
ratio == 0.3);
TEST_ASSERT_VAL("failed to compute metric",
compute_metric("DCache_L2_Misses", vals, &ratio) == 0);
TEST_ASSERT_VAL("DCache_L2_Misses failed, wrong ratio",
ratio == 0.7);
return 0;
}
perf metric: Add recursion check when processing nested metrics Keeping the stack of nested metrics via 'struct expr_id' objects and checking if we are in recursion via already processed metric. The stack is implemented as static array within the struct egroup with 100 entries, which should be enough nesting depth for any metric we have or plan to have at the moment. Adding test that simulates the recursion and checks we can detect it. Committer notes: Bumped RECURSION_ID_MAX to 1000 as per Jiri's reply to Paul Clark on the patch series e-mail discussion. Fixed these: tests/parse-metric.c:308:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, ^ util/metricgroup.c:924:28: error: missing field 'parent' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:28: error: missing field 'cnt' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200719181320.785305-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-20 02:13:16 +08:00
static int test_recursion_fail(void)
{
double ratio;
struct value vals[] = {
{ .event = "inst_retired.any", .val = 300 },
{ .event = "cpu_clk_unhalted.thread", .val = 200 },
{ .event = NULL, },
};
TEST_ASSERT_VAL("failed to find recursion",
compute_metric("M1", vals, &ratio) == -1);
TEST_ASSERT_VAL("failed to find recursion",
compute_metric("M3", vals, &ratio) == -1);
return 0;
}
int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused)
{
TEST_ASSERT_VAL("IPC failed", test_ipc() == 0);
perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-03 05:47:41 +08:00
TEST_ASSERT_VAL("frontend failed", test_frontend() == 0);
TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0);
TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0);
perf metric: Add recursion check when processing nested metrics Keeping the stack of nested metrics via 'struct expr_id' objects and checking if we are in recursion via already processed metric. The stack is implemented as static array within the struct egroup with 100 entries, which should be enough nesting depth for any metric we have or plan to have at the moment. Adding test that simulates the recursion and checks we can detect it. Committer notes: Bumped RECURSION_ID_MAX to 1000 as per Jiri's reply to Paul Clark on the patch series e-mail discussion. Fixed these: tests/parse-metric.c:308:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, ^ util/metricgroup.c:924:28: error: missing field 'parent' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:26: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces] struct expr_ids ids = { 0 }; ^ {} util/metricgroup.c:924:28: error: missing field 'cnt' initializer [-Werror,-Wmissing-field-initializers] struct expr_ids ids = { 0 }; ^ Signed-off-by: Jiri Olsa <jolsa@kernel.org> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: John Garry <john.garry@huawei.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200719181320.785305-16-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-20 02:13:16 +08:00
TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0);
return 0;
}