[PATCH 11/19] perf metric: Compute referenced metrics
Adding computation (expr__parse call) of referenced metric at the point when it needs to be resolved during the parent metric computation. Once the inner metric is computed, the result is stored and used if there's another usage of that metric. Signed-off-by: Jiri Olsa Reviewed-by: Kajol Jain Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: John Garry Cc: Michael Petlan Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200719181320.785305-12-jo...@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 31 +++ tools/perf/util/expr.h | 3 +++ tools/perf/util/expr.y | 4 ++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index d3997c2b4a90..a346ca590513 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -112,6 +112,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) */ data_ptr->ref.metric_name = ref->metric_name; data_ptr->ref.metric_expr = ref->metric_expr; + data_ptr->ref.counted = false; data_ptr->is_ref = true; ret = hashmap__set(>ids, name, data_ptr, @@ -133,6 +134,34 @@ int expr__get_id(struct expr_parse_ctx *ctx, const char *id, return hashmap__find(>ids, id, (void **)data) ? 0 : -1; } +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, +struct expr_id_data **datap) +{ + struct expr_id_data *data; + + if (expr__get_id(ctx, id, datap) || !*datap) { + pr_debug("%s not found\n", id); + return -1; + } + + data = *datap; + + pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", + data->is_ref, data->ref.counted, data->val, id); + + if (data->is_ref && !data->ref.counted) { + data->ref.counted = true; + pr_debug("processing metric: %s ENTRY\n", id); + if (expr__parse(>val, ctx, data->ref.metric_expr, 1)) { + pr_debug("%s failed to count\n", id); + return -1; + } + pr_debug("processing metric: %s EXIT: %f\n", id, data->val); + } + + return 0; +} + void expr__del_id(struct expr_parse_ctx *ctx, const char *id) { struct expr_id_data *old_val = NULL; @@ -173,6 +202,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, void *scanner; int ret; + pr_debug2("parsing metric: %s\n", expr); + ret = expr_lex_init_extra(_ctx, ); if (ret) return ret; diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 81d04ff7f857..9ed208d93418 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -23,6 +23,7 @@ struct expr_id_data { struct { const char *metric_name; const char *metric_expr; + bool counted; } ref; }; @@ -42,6 +43,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data); +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, +struct expr_id_data **datap); int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime); int expr__find_other(const char *expr, const char *one, diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 0d4f5d324be7..d34b370391c6 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -88,11 +88,11 @@ expr: NUMBER | ID{ struct expr_id_data *data; - if (expr__get_id(ctx, $1, ) || !data) { - pr_debug("%s not found\n", $1); + if (expr__resolve_id(ctx, $1, )) { free($1); YYABORT; } + $$ = data->val; free($1); } -- 2.25.4
Re: [PATCH 11/19] perf metric: Compute referenced metrics
Em Sun, Jul 26, 2020 at 02:49:04PM +0530, kajoljain escreveu: > > > On 7/19/20 11:43 PM, Jiri Olsa wrote: > > Adding computation (expr__parse call) of referenced metric at > > the point when it needs to be resolved during the parent metric > > computation. > > > > Once the inner metric is computed, the result is stored and > > used if there's another usage of that metric. > > > > Acked-by: Ian Rogers > > Signed-off-by: Jiri Olsa > > Reviewed-By : Kajol Jain Thanks, applied. - Arnaldo > Thanks, > Kajol Jain > > --- > > tools/perf/util/expr.c | 31 +++ > > tools/perf/util/expr.h | 3 +++ > > tools/perf/util/expr.y | 4 ++-- > > 3 files changed, 36 insertions(+), 2 deletions(-) > > > > diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c > > index d3997c2b4a90..a346ca590513 100644 > > --- a/tools/perf/util/expr.c > > +++ b/tools/perf/util/expr.c > > @@ -112,6 +112,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct > > metric_ref *ref) > > */ > > data_ptr->ref.metric_name = ref->metric_name; > > data_ptr->ref.metric_expr = ref->metric_expr; > > + data_ptr->ref.counted = false; > > data_ptr->is_ref = true; > > > > ret = hashmap__set(>ids, name, data_ptr, > > @@ -133,6 +134,34 @@ int expr__get_id(struct expr_parse_ctx *ctx, const > > char *id, > > return hashmap__find(>ids, id, (void **)data) ? 0 : -1; > > } > > > > +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, > > +struct expr_id_data **datap) > > +{ > > + struct expr_id_data *data; > > + > > + if (expr__get_id(ctx, id, datap) || !*datap) { > > + pr_debug("%s not found\n", id); > > + return -1; > > + } > > + > > + data = *datap; > > + > > + pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", > > + data->is_ref, data->ref.counted, data->val, id); > > + > > + if (data->is_ref && !data->ref.counted) { > > + data->ref.counted = true; > > + pr_debug("processing metric: %s ENTRY\n", id); > > + if (expr__parse(>val, ctx, data->ref.metric_expr, 1)) { > > + pr_debug("%s failed to count\n", id); > > + return -1; > > + } > > + pr_debug("processing metric: %s EXIT: %f\n", id, data->val); > > + } > > + > > + return 0; > > +} > > + > > void expr__del_id(struct expr_parse_ctx *ctx, const char *id) > > { > > struct expr_id_data *old_val = NULL; > > @@ -173,6 +202,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, > > const char *expr, > > void *scanner; > > int ret; > > > > + pr_debug2("parsing metric: %s\n", expr); > > + > > ret = expr_lex_init_extra(_ctx, ); > > if (ret) > > return ret; > > diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h > > index 81d04ff7f857..9ed208d93418 100644 > > --- a/tools/perf/util/expr.h > > +++ b/tools/perf/util/expr.h > > @@ -23,6 +23,7 @@ struct expr_id_data { > > struct { > > const char *metric_name; > > const char *metric_expr; > > + bool counted; > > } ref; > > }; > > > > @@ -42,6 +43,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const > > char *id, double val); > > int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); > > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, > > struct expr_id_data **data); > > +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, > > +struct expr_id_data **datap); > > int expr__parse(double *final_val, struct expr_parse_ctx *ctx, > > const char *expr, int runtime); > > int expr__find_other(const char *expr, const char *one, > > diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y > > index 0d4f5d324be7..d34b370391c6 100644 > > --- a/tools/perf/util/expr.y > > +++ b/tools/perf/util/expr.y > > @@ -88,11 +88,11 @@ expr: NUMBER > > | ID{ > > struct expr_id_data *data; > > > > - if (expr__get_id(ctx, $1, ) || > > !data) { > > - pr_debug("%s not found\n", $1); > > + if (expr__resolve_id(ctx, $1, )) { > > free($1); > > YYABORT; > > } > > + > > $$ = data->val; > > free($1); > > } > > -- - Arnaldo
Re: [PATCH 11/19] perf metric: Compute referenced metrics
On 7/19/20 11:43 PM, Jiri Olsa wrote: > Adding computation (expr__parse call) of referenced metric at > the point when it needs to be resolved during the parent metric > computation. > > Once the inner metric is computed, the result is stored and > used if there's another usage of that metric. > > Acked-by: Ian Rogers > Signed-off-by: Jiri Olsa Reviewed-By : Kajol Jain Thanks, Kajol Jain > --- > tools/perf/util/expr.c | 31 +++ > tools/perf/util/expr.h | 3 +++ > tools/perf/util/expr.y | 4 ++-- > 3 files changed, 36 insertions(+), 2 deletions(-) > > diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c > index d3997c2b4a90..a346ca590513 100644 > --- a/tools/perf/util/expr.c > +++ b/tools/perf/util/expr.c > @@ -112,6 +112,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct > metric_ref *ref) >*/ > data_ptr->ref.metric_name = ref->metric_name; > data_ptr->ref.metric_expr = ref->metric_expr; > + data_ptr->ref.counted = false; > data_ptr->is_ref = true; > > ret = hashmap__set(>ids, name, data_ptr, > @@ -133,6 +134,34 @@ int expr__get_id(struct expr_parse_ctx *ctx, const char > *id, > return hashmap__find(>ids, id, (void **)data) ? 0 : -1; > } > > +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, > + struct expr_id_data **datap) > +{ > + struct expr_id_data *data; > + > + if (expr__get_id(ctx, id, datap) || !*datap) { > + pr_debug("%s not found\n", id); > + return -1; > + } > + > + data = *datap; > + > + pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", > + data->is_ref, data->ref.counted, data->val, id); > + > + if (data->is_ref && !data->ref.counted) { > + data->ref.counted = true; > + pr_debug("processing metric: %s ENTRY\n", id); > + if (expr__parse(>val, ctx, data->ref.metric_expr, 1)) { > + pr_debug("%s failed to count\n", id); > + return -1; > + } > + pr_debug("processing metric: %s EXIT: %f\n", id, data->val); > + } > + > + return 0; > +} > + > void expr__del_id(struct expr_parse_ctx *ctx, const char *id) > { > struct expr_id_data *old_val = NULL; > @@ -173,6 +202,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, > const char *expr, > void *scanner; > int ret; > > + pr_debug2("parsing metric: %s\n", expr); > + > ret = expr_lex_init_extra(_ctx, ); > if (ret) > return ret; > diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h > index 81d04ff7f857..9ed208d93418 100644 > --- a/tools/perf/util/expr.h > +++ b/tools/perf/util/expr.h > @@ -23,6 +23,7 @@ struct expr_id_data { > struct { > const char *metric_name; > const char *metric_expr; > + bool counted; > } ref; > }; > > @@ -42,6 +43,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char > *id, double val); > int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); > int expr__get_id(struct expr_parse_ctx *ctx, const char *id, >struct expr_id_data **data); > +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, > + struct expr_id_data **datap); > int expr__parse(double *final_val, struct expr_parse_ctx *ctx, > const char *expr, int runtime); > int expr__find_other(const char *expr, const char *one, > diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y > index 0d4f5d324be7..d34b370391c6 100644 > --- a/tools/perf/util/expr.y > +++ b/tools/perf/util/expr.y > @@ -88,11 +88,11 @@ expr: NUMBER > | ID{ > struct expr_id_data *data; > > - if (expr__get_id(ctx, $1, ) || > !data) { > - pr_debug("%s not found\n", $1); > + if (expr__resolve_id(ctx, $1, )) { > free($1); > YYABORT; > } > + > $$ = data->val; > free($1); > } >
[PATCH 11/19] perf metric: Compute referenced metrics
Adding computation (expr__parse call) of referenced metric at the point when it needs to be resolved during the parent metric computation. Once the inner metric is computed, the result is stored and used if there's another usage of that metric. Acked-by: Ian Rogers Signed-off-by: Jiri Olsa --- tools/perf/util/expr.c | 31 +++ tools/perf/util/expr.h | 3 +++ tools/perf/util/expr.y | 4 ++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index d3997c2b4a90..a346ca590513 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -112,6 +112,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) */ data_ptr->ref.metric_name = ref->metric_name; data_ptr->ref.metric_expr = ref->metric_expr; + data_ptr->ref.counted = false; data_ptr->is_ref = true; ret = hashmap__set(>ids, name, data_ptr, @@ -133,6 +134,34 @@ int expr__get_id(struct expr_parse_ctx *ctx, const char *id, return hashmap__find(>ids, id, (void **)data) ? 0 : -1; } +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, +struct expr_id_data **datap) +{ + struct expr_id_data *data; + + if (expr__get_id(ctx, id, datap) || !*datap) { + pr_debug("%s not found\n", id); + return -1; + } + + data = *datap; + + pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", + data->is_ref, data->ref.counted, data->val, id); + + if (data->is_ref && !data->ref.counted) { + data->ref.counted = true; + pr_debug("processing metric: %s ENTRY\n", id); + if (expr__parse(>val, ctx, data->ref.metric_expr, 1)) { + pr_debug("%s failed to count\n", id); + return -1; + } + pr_debug("processing metric: %s EXIT: %f\n", id, data->val); + } + + return 0; +} + void expr__del_id(struct expr_parse_ctx *ctx, const char *id) { struct expr_id_data *old_val = NULL; @@ -173,6 +202,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, void *scanner; int ret; + pr_debug2("parsing metric: %s\n", expr); + ret = expr_lex_init_extra(_ctx, ); if (ret) return ret; diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 81d04ff7f857..9ed208d93418 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -23,6 +23,7 @@ struct expr_id_data { struct { const char *metric_name; const char *metric_expr; + bool counted; } ref; }; @@ -42,6 +43,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val); int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref); int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data); +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, +struct expr_id_data **datap); int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime); int expr__find_other(const char *expr, const char *one, diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 0d4f5d324be7..d34b370391c6 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -88,11 +88,11 @@ expr: NUMBER | ID{ struct expr_id_data *data; - if (expr__get_id(ctx, $1, ) || !data) { - pr_debug("%s not found\n", $1); + if (expr__resolve_id(ctx, $1, )) { free($1); YYABORT; } + $$ = data->val; free($1); } -- 2.25.4