162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <math.h> 362306a36Sopenharmony_ci#include <stdio.h> 462306a36Sopenharmony_ci#include "evsel.h" 562306a36Sopenharmony_ci#include "stat.h" 662306a36Sopenharmony_ci#include "color.h" 762306a36Sopenharmony_ci#include "debug.h" 862306a36Sopenharmony_ci#include "pmu.h" 962306a36Sopenharmony_ci#include "rblist.h" 1062306a36Sopenharmony_ci#include "evlist.h" 1162306a36Sopenharmony_ci#include "expr.h" 1262306a36Sopenharmony_ci#include "metricgroup.h" 1362306a36Sopenharmony_ci#include "cgroup.h" 1462306a36Sopenharmony_ci#include "units.h" 1562306a36Sopenharmony_ci#include <linux/zalloc.h> 1662306a36Sopenharmony_ci#include "iostat.h" 1762306a36Sopenharmony_ci#include "util/hashmap.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistruct stats walltime_nsecs_stats; 2062306a36Sopenharmony_cistruct rusage_stats ru_stats; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cienum { 2362306a36Sopenharmony_ci CTX_BIT_USER = 1 << 0, 2462306a36Sopenharmony_ci CTX_BIT_KERNEL = 1 << 1, 2562306a36Sopenharmony_ci CTX_BIT_HV = 1 << 2, 2662306a36Sopenharmony_ci CTX_BIT_HOST = 1 << 3, 2762306a36Sopenharmony_ci CTX_BIT_IDLE = 1 << 4, 2862306a36Sopenharmony_ci CTX_BIT_MAX = 1 << 5, 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cienum stat_type { 3262306a36Sopenharmony_ci STAT_NONE = 0, 3362306a36Sopenharmony_ci STAT_NSECS, 3462306a36Sopenharmony_ci STAT_CYCLES, 3562306a36Sopenharmony_ci STAT_INSTRUCTIONS, 3662306a36Sopenharmony_ci STAT_STALLED_CYCLES_FRONT, 3762306a36Sopenharmony_ci STAT_STALLED_CYCLES_BACK, 3862306a36Sopenharmony_ci STAT_BRANCHES, 3962306a36Sopenharmony_ci STAT_BRANCH_MISS, 4062306a36Sopenharmony_ci STAT_CACHE_REFS, 4162306a36Sopenharmony_ci STAT_CACHE_MISSES, 4262306a36Sopenharmony_ci STAT_L1_DCACHE, 4362306a36Sopenharmony_ci STAT_L1_ICACHE, 4462306a36Sopenharmony_ci STAT_LL_CACHE, 4562306a36Sopenharmony_ci STAT_ITLB_CACHE, 4662306a36Sopenharmony_ci STAT_DTLB_CACHE, 4762306a36Sopenharmony_ci STAT_L1D_MISS, 4862306a36Sopenharmony_ci STAT_L1I_MISS, 4962306a36Sopenharmony_ci STAT_LL_MISS, 5062306a36Sopenharmony_ci STAT_DTLB_MISS, 5162306a36Sopenharmony_ci STAT_ITLB_MISS, 5262306a36Sopenharmony_ci STAT_MAX 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic int evsel_context(const struct evsel *evsel) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci int ctx = 0; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (evsel->core.attr.exclude_kernel) 6062306a36Sopenharmony_ci ctx |= CTX_BIT_KERNEL; 6162306a36Sopenharmony_ci if (evsel->core.attr.exclude_user) 6262306a36Sopenharmony_ci ctx |= CTX_BIT_USER; 6362306a36Sopenharmony_ci if (evsel->core.attr.exclude_hv) 6462306a36Sopenharmony_ci ctx |= CTX_BIT_HV; 6562306a36Sopenharmony_ci if (evsel->core.attr.exclude_host) 6662306a36Sopenharmony_ci ctx |= CTX_BIT_HOST; 6762306a36Sopenharmony_ci if (evsel->core.attr.exclude_idle) 6862306a36Sopenharmony_ci ctx |= CTX_BIT_IDLE; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return ctx; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_civoid perf_stat__reset_shadow_stats(void) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); 7662306a36Sopenharmony_ci memset(&ru_stats, 0, sizeof(ru_stats)); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic enum stat_type evsel__stat_type(const struct evsel *evsel) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci /* Fake perf_hw_cache_op_id values for use with evsel__match. */ 8262306a36Sopenharmony_ci u64 PERF_COUNT_hw_cache_l1d_miss = PERF_COUNT_HW_CACHE_L1D | 8362306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 8462306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); 8562306a36Sopenharmony_ci u64 PERF_COUNT_hw_cache_l1i_miss = PERF_COUNT_HW_CACHE_L1I | 8662306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 8762306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); 8862306a36Sopenharmony_ci u64 PERF_COUNT_hw_cache_ll_miss = PERF_COUNT_HW_CACHE_LL | 8962306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 9062306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); 9162306a36Sopenharmony_ci u64 PERF_COUNT_hw_cache_dtlb_miss = PERF_COUNT_HW_CACHE_DTLB | 9262306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 9362306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); 9462306a36Sopenharmony_ci u64 PERF_COUNT_hw_cache_itlb_miss = PERF_COUNT_HW_CACHE_ITLB | 9562306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 9662306a36Sopenharmony_ci ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (evsel__is_clock(evsel)) 9962306a36Sopenharmony_ci return STAT_NSECS; 10062306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) 10162306a36Sopenharmony_ci return STAT_CYCLES; 10262306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) 10362306a36Sopenharmony_ci return STAT_INSTRUCTIONS; 10462306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 10562306a36Sopenharmony_ci return STAT_STALLED_CYCLES_FRONT; 10662306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 10762306a36Sopenharmony_ci return STAT_STALLED_CYCLES_BACK; 10862306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 10962306a36Sopenharmony_ci return STAT_BRANCHES; 11062306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) 11162306a36Sopenharmony_ci return STAT_BRANCH_MISS; 11262306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_CACHE_REFERENCES)) 11362306a36Sopenharmony_ci return STAT_CACHE_REFS; 11462306a36Sopenharmony_ci else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) 11562306a36Sopenharmony_ci return STAT_CACHE_MISSES; 11662306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, HW_CACHE_L1D)) 11762306a36Sopenharmony_ci return STAT_L1_DCACHE; 11862306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, HW_CACHE_L1I)) 11962306a36Sopenharmony_ci return STAT_L1_ICACHE; 12062306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, HW_CACHE_LL)) 12162306a36Sopenharmony_ci return STAT_LL_CACHE; 12262306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, HW_CACHE_DTLB)) 12362306a36Sopenharmony_ci return STAT_DTLB_CACHE; 12462306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, HW_CACHE_ITLB)) 12562306a36Sopenharmony_ci return STAT_ITLB_CACHE; 12662306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, hw_cache_l1d_miss)) 12762306a36Sopenharmony_ci return STAT_L1D_MISS; 12862306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, hw_cache_l1i_miss)) 12962306a36Sopenharmony_ci return STAT_L1I_MISS; 13062306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, hw_cache_ll_miss)) 13162306a36Sopenharmony_ci return STAT_LL_MISS; 13262306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, hw_cache_dtlb_miss)) 13362306a36Sopenharmony_ci return STAT_DTLB_MISS; 13462306a36Sopenharmony_ci else if (evsel__match(evsel, HW_CACHE, hw_cache_itlb_miss)) 13562306a36Sopenharmony_ci return STAT_ITLB_MISS; 13662306a36Sopenharmony_ci return STAT_NONE; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic const char *get_ratio_color(const double ratios[3], double val) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci const char *color = PERF_COLOR_NORMAL; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (val > ratios[0]) 14462306a36Sopenharmony_ci color = PERF_COLOR_RED; 14562306a36Sopenharmony_ci else if (val > ratios[1]) 14662306a36Sopenharmony_ci color = PERF_COLOR_MAGENTA; 14762306a36Sopenharmony_ci else if (val > ratios[2]) 14862306a36Sopenharmony_ci color = PERF_COLOR_YELLOW; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return color; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type type) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci const struct evsel *cur; 15662306a36Sopenharmony_ci int evsel_ctx = evsel_context(evsel); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci evlist__for_each_entry(evsel->evlist, cur) { 15962306a36Sopenharmony_ci struct perf_stat_aggr *aggr; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Ignore the evsel that is being searched from. */ 16262306a36Sopenharmony_ci if (evsel == cur) 16362306a36Sopenharmony_ci continue; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Ignore evsels that are part of different groups. */ 16662306a36Sopenharmony_ci if (evsel->core.leader->nr_members > 1 && 16762306a36Sopenharmony_ci evsel->core.leader != cur->core.leader) 16862306a36Sopenharmony_ci continue; 16962306a36Sopenharmony_ci /* Ignore evsels with mismatched modifiers. */ 17062306a36Sopenharmony_ci if (evsel_ctx != evsel_context(cur)) 17162306a36Sopenharmony_ci continue; 17262306a36Sopenharmony_ci /* Ignore if not the cgroup we're looking for. */ 17362306a36Sopenharmony_ci if (evsel->cgrp != cur->cgrp) 17462306a36Sopenharmony_ci continue; 17562306a36Sopenharmony_ci /* Ignore if not the stat we're looking for. */ 17662306a36Sopenharmony_ci if (type != evsel__stat_type(cur)) 17762306a36Sopenharmony_ci continue; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci aggr = &cur->stats->aggr[aggr_idx]; 18062306a36Sopenharmony_ci if (type == STAT_NSECS) 18162306a36Sopenharmony_ci return aggr->counts.val; 18262306a36Sopenharmony_ci return aggr->counts.val * cur->scale; 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci return 0.0; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic void print_ratio(struct perf_stat_config *config, 18862306a36Sopenharmony_ci const struct evsel *evsel, int aggr_idx, 18962306a36Sopenharmony_ci double numerator, struct perf_stat_output_ctx *out, 19062306a36Sopenharmony_ci enum stat_type denominator_type, 19162306a36Sopenharmony_ci const double color_ratios[3], const char *unit) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci double denominator = find_stat(evsel, aggr_idx, denominator_type); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (numerator && denominator) { 19662306a36Sopenharmony_ci double ratio = numerator / denominator * 100.0; 19762306a36Sopenharmony_ci const char *color = get_ratio_color(color_ratios, ratio); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci out->print_metric(config, out->ctx, color, "%7.2f%%", unit, ratio); 20062306a36Sopenharmony_ci } else 20162306a36Sopenharmony_ci out->print_metric(config, out->ctx, NULL, NULL, unit, 0); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic void print_stalled_cycles_front(struct perf_stat_config *config, 20562306a36Sopenharmony_ci const struct evsel *evsel, 20662306a36Sopenharmony_ci int aggr_idx, double stalled, 20762306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci static const double color_ratios[3] = {50.0, 30.0, 10.0}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios, 21262306a36Sopenharmony_ci "frontend cycles idle"); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic void print_stalled_cycles_back(struct perf_stat_config *config, 21662306a36Sopenharmony_ci const struct evsel *evsel, 21762306a36Sopenharmony_ci int aggr_idx, double stalled, 21862306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci static const double color_ratios[3] = {75.0, 50.0, 20.0}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios, 22362306a36Sopenharmony_ci "backend cycles idle"); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic void print_branch_miss(struct perf_stat_config *config, 22762306a36Sopenharmony_ci const struct evsel *evsel, 22862306a36Sopenharmony_ci int aggr_idx, double misses, 22962306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, color_ratios, 23462306a36Sopenharmony_ci "of all branches"); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic void print_l1d_miss(struct perf_stat_config *config, 23862306a36Sopenharmony_ci const struct evsel *evsel, 23962306a36Sopenharmony_ci int aggr_idx, double misses, 24062306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, color_ratios, 24562306a36Sopenharmony_ci "of all L1-dcache accesses"); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void print_l1i_miss(struct perf_stat_config *config, 24962306a36Sopenharmony_ci const struct evsel *evsel, 25062306a36Sopenharmony_ci int aggr_idx, double misses, 25162306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, color_ratios, 25662306a36Sopenharmony_ci "of all L1-icache accesses"); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void print_ll_miss(struct perf_stat_config *config, 26062306a36Sopenharmony_ci const struct evsel *evsel, 26162306a36Sopenharmony_ci int aggr_idx, double misses, 26262306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, color_ratios, 26762306a36Sopenharmony_ci "of all LL-cache accesses"); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic void print_dtlb_miss(struct perf_stat_config *config, 27162306a36Sopenharmony_ci const struct evsel *evsel, 27262306a36Sopenharmony_ci int aggr_idx, double misses, 27362306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, color_ratios, 27862306a36Sopenharmony_ci "of all dTLB cache accesses"); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic void print_itlb_miss(struct perf_stat_config *config, 28262306a36Sopenharmony_ci const struct evsel *evsel, 28362306a36Sopenharmony_ci int aggr_idx, double misses, 28462306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, color_ratios, 28962306a36Sopenharmony_ci "of all iTLB cache accesses"); 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic void print_cache_miss(struct perf_stat_config *config, 29362306a36Sopenharmony_ci const struct evsel *evsel, 29462306a36Sopenharmony_ci int aggr_idx, double misses, 29562306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci static const double color_ratios[3] = {20.0, 10.0, 5.0}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, color_ratios, 30062306a36Sopenharmony_ci "of all cache refs"); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic void print_instructions(struct perf_stat_config *config, 30462306a36Sopenharmony_ci const struct evsel *evsel, 30562306a36Sopenharmony_ci int aggr_idx, double instructions, 30662306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci print_metric_t print_metric = out->print_metric; 30962306a36Sopenharmony_ci void *ctxp = out->ctx; 31062306a36Sopenharmony_ci double cycles = find_stat(evsel, aggr_idx, STAT_CYCLES); 31162306a36Sopenharmony_ci double max_stalled = max(find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_FRONT), 31262306a36Sopenharmony_ci find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_BACK)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (cycles) { 31562306a36Sopenharmony_ci print_metric(config, ctxp, NULL, "%7.2f ", "insn per cycle", 31662306a36Sopenharmony_ci instructions / cycles); 31762306a36Sopenharmony_ci } else 31862306a36Sopenharmony_ci print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (max_stalled && instructions) { 32162306a36Sopenharmony_ci out->new_line(config, ctxp); 32262306a36Sopenharmony_ci print_metric(config, ctxp, NULL, "%7.2f ", "stalled cycles per insn", 32362306a36Sopenharmony_ci max_stalled / instructions); 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic void print_cycles(struct perf_stat_config *config, 32862306a36Sopenharmony_ci const struct evsel *evsel, 32962306a36Sopenharmony_ci int aggr_idx, double cycles, 33062306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci double nsecs = find_stat(evsel, aggr_idx, STAT_NSECS); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (cycles && nsecs) { 33562306a36Sopenharmony_ci double ratio = cycles / nsecs; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci out->print_metric(config, out->ctx, NULL, "%8.3f", "GHz", ratio); 33862306a36Sopenharmony_ci } else 33962306a36Sopenharmony_ci out->print_metric(config, out->ctx, NULL, NULL, "GHz", 0); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic void print_nsecs(struct perf_stat_config *config, 34362306a36Sopenharmony_ci const struct evsel *evsel, 34462306a36Sopenharmony_ci int aggr_idx __maybe_unused, double nsecs, 34562306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci print_metric_t print_metric = out->print_metric; 34862306a36Sopenharmony_ci void *ctxp = out->ctx; 34962306a36Sopenharmony_ci double wall_time = avg_stats(&walltime_nsecs_stats); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (wall_time) { 35262306a36Sopenharmony_ci print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized", 35362306a36Sopenharmony_ci nsecs / (wall_time * evsel->scale)); 35462306a36Sopenharmony_ci } else 35562306a36Sopenharmony_ci print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0); 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic int prepare_metric(struct evsel **metric_events, 35962306a36Sopenharmony_ci struct metric_ref *metric_refs, 36062306a36Sopenharmony_ci struct expr_parse_ctx *pctx, 36162306a36Sopenharmony_ci int aggr_idx) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci int i; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci for (i = 0; metric_events[i]; i++) { 36662306a36Sopenharmony_ci char *n; 36762306a36Sopenharmony_ci double val; 36862306a36Sopenharmony_ci int source_count = 0; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (evsel__is_tool(metric_events[i])) { 37162306a36Sopenharmony_ci struct stats *stats; 37262306a36Sopenharmony_ci double scale; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci switch (metric_events[i]->tool_event) { 37562306a36Sopenharmony_ci case PERF_TOOL_DURATION_TIME: 37662306a36Sopenharmony_ci stats = &walltime_nsecs_stats; 37762306a36Sopenharmony_ci scale = 1e-9; 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci case PERF_TOOL_USER_TIME: 38062306a36Sopenharmony_ci stats = &ru_stats.ru_utime_usec_stat; 38162306a36Sopenharmony_ci scale = 1e-6; 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci case PERF_TOOL_SYSTEM_TIME: 38462306a36Sopenharmony_ci stats = &ru_stats.ru_stime_usec_stat; 38562306a36Sopenharmony_ci scale = 1e-6; 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci case PERF_TOOL_NONE: 38862306a36Sopenharmony_ci pr_err("Invalid tool event 'none'"); 38962306a36Sopenharmony_ci abort(); 39062306a36Sopenharmony_ci case PERF_TOOL_MAX: 39162306a36Sopenharmony_ci pr_err("Invalid tool event 'max'"); 39262306a36Sopenharmony_ci abort(); 39362306a36Sopenharmony_ci default: 39462306a36Sopenharmony_ci pr_err("Unknown tool event '%s'", evsel__name(metric_events[i])); 39562306a36Sopenharmony_ci abort(); 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci val = avg_stats(stats) * scale; 39862306a36Sopenharmony_ci source_count = 1; 39962306a36Sopenharmony_ci } else { 40062306a36Sopenharmony_ci struct perf_stat_evsel *ps = metric_events[i]->stats; 40162306a36Sopenharmony_ci struct perf_stat_aggr *aggr = &ps->aggr[aggr_idx]; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (!aggr) 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (!metric_events[i]->supported) { 40762306a36Sopenharmony_ci /* 40862306a36Sopenharmony_ci * Not supported events will have a count of 0, 40962306a36Sopenharmony_ci * which can be confusing in a 41062306a36Sopenharmony_ci * metric. Explicitly set the value to NAN. Not 41162306a36Sopenharmony_ci * counted events (enable time of 0) are read as 41262306a36Sopenharmony_ci * 0. 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_ci val = NAN; 41562306a36Sopenharmony_ci source_count = 0; 41662306a36Sopenharmony_ci } else { 41762306a36Sopenharmony_ci val = aggr->counts.val; 41862306a36Sopenharmony_ci source_count = evsel__source_count(metric_events[i]); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci n = strdup(evsel__metric_id(metric_events[i])); 42262306a36Sopenharmony_ci if (!n) 42362306a36Sopenharmony_ci return -ENOMEM; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci expr__add_id_val_source_count(pctx, n, val, source_count); 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci for (int j = 0; metric_refs && metric_refs[j].metric_name; j++) { 42962306a36Sopenharmony_ci int ret = expr__add_ref(pctx, &metric_refs[j]); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (ret) 43262306a36Sopenharmony_ci return ret; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return i; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic void generic_metric(struct perf_stat_config *config, 43962306a36Sopenharmony_ci const char *metric_expr, 44062306a36Sopenharmony_ci const char *metric_threshold, 44162306a36Sopenharmony_ci struct evsel **metric_events, 44262306a36Sopenharmony_ci struct metric_ref *metric_refs, 44362306a36Sopenharmony_ci char *name, 44462306a36Sopenharmony_ci const char *metric_name, 44562306a36Sopenharmony_ci const char *metric_unit, 44662306a36Sopenharmony_ci int runtime, 44762306a36Sopenharmony_ci int aggr_idx, 44862306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci print_metric_t print_metric = out->print_metric; 45162306a36Sopenharmony_ci struct expr_parse_ctx *pctx; 45262306a36Sopenharmony_ci double ratio, scale, threshold; 45362306a36Sopenharmony_ci int i; 45462306a36Sopenharmony_ci void *ctxp = out->ctx; 45562306a36Sopenharmony_ci const char *color = NULL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci pctx = expr__ctx_new(); 45862306a36Sopenharmony_ci if (!pctx) 45962306a36Sopenharmony_ci return; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (config->user_requested_cpu_list) 46262306a36Sopenharmony_ci pctx->sctx.user_requested_cpu_list = strdup(config->user_requested_cpu_list); 46362306a36Sopenharmony_ci pctx->sctx.runtime = runtime; 46462306a36Sopenharmony_ci pctx->sctx.system_wide = config->system_wide; 46562306a36Sopenharmony_ci i = prepare_metric(metric_events, metric_refs, pctx, aggr_idx); 46662306a36Sopenharmony_ci if (i < 0) { 46762306a36Sopenharmony_ci expr__ctx_free(pctx); 46862306a36Sopenharmony_ci return; 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci if (!metric_events[i]) { 47162306a36Sopenharmony_ci if (expr__parse(&ratio, pctx, metric_expr) == 0) { 47262306a36Sopenharmony_ci char *unit; 47362306a36Sopenharmony_ci char metric_bf[64]; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci if (metric_threshold && 47662306a36Sopenharmony_ci expr__parse(&threshold, pctx, metric_threshold) == 0 && 47762306a36Sopenharmony_ci !isnan(threshold)) { 47862306a36Sopenharmony_ci color = fpclassify(threshold) == FP_ZERO 47962306a36Sopenharmony_ci ? PERF_COLOR_GREEN : PERF_COLOR_RED; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (metric_unit && metric_name) { 48362306a36Sopenharmony_ci if (perf_pmu__convert_scale(metric_unit, 48462306a36Sopenharmony_ci &unit, &scale) >= 0) { 48562306a36Sopenharmony_ci ratio *= scale; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci if (strstr(metric_expr, "?")) 48862306a36Sopenharmony_ci scnprintf(metric_bf, sizeof(metric_bf), 48962306a36Sopenharmony_ci "%s %s_%d", unit, metric_name, runtime); 49062306a36Sopenharmony_ci else 49162306a36Sopenharmony_ci scnprintf(metric_bf, sizeof(metric_bf), 49262306a36Sopenharmony_ci "%s %s", unit, metric_name); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci print_metric(config, ctxp, color, "%8.1f", 49562306a36Sopenharmony_ci metric_bf, ratio); 49662306a36Sopenharmony_ci } else { 49762306a36Sopenharmony_ci print_metric(config, ctxp, color, "%8.2f", 49862306a36Sopenharmony_ci metric_name ? 49962306a36Sopenharmony_ci metric_name : 50062306a36Sopenharmony_ci out->force_header ? name : "", 50162306a36Sopenharmony_ci ratio); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci } else { 50462306a36Sopenharmony_ci print_metric(config, ctxp, color, /*unit=*/NULL, 50562306a36Sopenharmony_ci out->force_header ? 50662306a36Sopenharmony_ci (metric_name ? metric_name : name) : "", 0); 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci } else { 50962306a36Sopenharmony_ci print_metric(config, ctxp, color, /*unit=*/NULL, 51062306a36Sopenharmony_ci out->force_header ? 51162306a36Sopenharmony_ci (metric_name ? metric_name : name) : "", 0); 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci expr__ctx_free(pctx); 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cidouble test_generic_metric(struct metric_expr *mexp, int aggr_idx) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci struct expr_parse_ctx *pctx; 52062306a36Sopenharmony_ci double ratio = 0.0; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci pctx = expr__ctx_new(); 52362306a36Sopenharmony_ci if (!pctx) 52462306a36Sopenharmony_ci return NAN; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (prepare_metric(mexp->metric_events, mexp->metric_refs, pctx, aggr_idx) < 0) 52762306a36Sopenharmony_ci goto out; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (expr__parse(&ratio, pctx, mexp->metric_expr)) 53062306a36Sopenharmony_ci ratio = 0.0; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ciout: 53362306a36Sopenharmony_ci expr__ctx_free(pctx); 53462306a36Sopenharmony_ci return ratio; 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic void perf_stat__print_metricgroup_header(struct perf_stat_config *config, 53862306a36Sopenharmony_ci struct evsel *evsel, 53962306a36Sopenharmony_ci void *ctxp, 54062306a36Sopenharmony_ci const char *name, 54162306a36Sopenharmony_ci struct perf_stat_output_ctx *out) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci bool need_full_name = perf_pmus__num_core_pmus() > 1; 54462306a36Sopenharmony_ci static const char *last_name; 54562306a36Sopenharmony_ci static const char *last_pmu; 54662306a36Sopenharmony_ci char full_name[64]; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* 54962306a36Sopenharmony_ci * A metricgroup may have several metric events, 55062306a36Sopenharmony_ci * e.g.,TopdownL1 on e-core of ADL. 55162306a36Sopenharmony_ci * The name has been output by the first metric 55262306a36Sopenharmony_ci * event. Only align with other metics from 55362306a36Sopenharmony_ci * different metric events. 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci if (last_name && !strcmp(last_name, name)) { 55662306a36Sopenharmony_ci if (!need_full_name || !strcmp(last_pmu, evsel->pmu_name)) { 55762306a36Sopenharmony_ci out->print_metricgroup_header(config, ctxp, NULL); 55862306a36Sopenharmony_ci return; 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (need_full_name) 56362306a36Sopenharmony_ci scnprintf(full_name, sizeof(full_name), "%s (%s)", name, evsel->pmu_name); 56462306a36Sopenharmony_ci else 56562306a36Sopenharmony_ci scnprintf(full_name, sizeof(full_name), "%s", name); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci out->print_metricgroup_header(config, ctxp, full_name); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci last_name = name; 57062306a36Sopenharmony_ci last_pmu = evsel->pmu_name; 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci/** 57462306a36Sopenharmony_ci * perf_stat__print_shadow_stats_metricgroup - Print out metrics associated with the evsel 57562306a36Sopenharmony_ci * For the non-default, all metrics associated 57662306a36Sopenharmony_ci * with the evsel are printed. 57762306a36Sopenharmony_ci * For the default mode, only the metrics from 57862306a36Sopenharmony_ci * the same metricgroup and the name of the 57962306a36Sopenharmony_ci * metricgroup are printed. To print the metrics 58062306a36Sopenharmony_ci * from the next metricgroup (if available), 58162306a36Sopenharmony_ci * invoke the function with correspoinding 58262306a36Sopenharmony_ci * metric_expr. 58362306a36Sopenharmony_ci */ 58462306a36Sopenharmony_civoid *perf_stat__print_shadow_stats_metricgroup(struct perf_stat_config *config, 58562306a36Sopenharmony_ci struct evsel *evsel, 58662306a36Sopenharmony_ci int aggr_idx, 58762306a36Sopenharmony_ci int *num, 58862306a36Sopenharmony_ci void *from, 58962306a36Sopenharmony_ci struct perf_stat_output_ctx *out, 59062306a36Sopenharmony_ci struct rblist *metric_events) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci struct metric_event *me; 59362306a36Sopenharmony_ci struct metric_expr *mexp = from; 59462306a36Sopenharmony_ci void *ctxp = out->ctx; 59562306a36Sopenharmony_ci bool header_printed = false; 59662306a36Sopenharmony_ci const char *name = NULL; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci me = metricgroup__lookup(metric_events, evsel, false); 59962306a36Sopenharmony_ci if (me == NULL) 60062306a36Sopenharmony_ci return NULL; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci if (!mexp) 60362306a36Sopenharmony_ci mexp = list_first_entry(&me->head, typeof(*mexp), nd); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci list_for_each_entry_from(mexp, &me->head, nd) { 60662306a36Sopenharmony_ci /* Print the display name of the Default metricgroup */ 60762306a36Sopenharmony_ci if (!config->metric_only && me->is_default) { 60862306a36Sopenharmony_ci if (!name) 60962306a36Sopenharmony_ci name = mexp->default_metricgroup_name; 61062306a36Sopenharmony_ci /* 61162306a36Sopenharmony_ci * Two or more metricgroup may share the same metric 61262306a36Sopenharmony_ci * event, e.g., TopdownL1 and TopdownL2 on SPR. 61362306a36Sopenharmony_ci * Return and print the prefix, e.g., noise, running 61462306a36Sopenharmony_ci * for the next metricgroup. 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_ci if (strcmp(name, mexp->default_metricgroup_name)) 61762306a36Sopenharmony_ci return (void *)mexp; 61862306a36Sopenharmony_ci /* Only print the name of the metricgroup once */ 61962306a36Sopenharmony_ci if (!header_printed) { 62062306a36Sopenharmony_ci header_printed = true; 62162306a36Sopenharmony_ci perf_stat__print_metricgroup_header(config, evsel, ctxp, 62262306a36Sopenharmony_ci name, out); 62362306a36Sopenharmony_ci } 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if ((*num)++ > 0) 62762306a36Sopenharmony_ci out->new_line(config, ctxp); 62862306a36Sopenharmony_ci generic_metric(config, mexp->metric_expr, mexp->metric_threshold, 62962306a36Sopenharmony_ci mexp->metric_events, mexp->metric_refs, evsel->name, 63062306a36Sopenharmony_ci mexp->metric_name, mexp->metric_unit, mexp->runtime, 63162306a36Sopenharmony_ci aggr_idx, out); 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci return NULL; 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_civoid perf_stat__print_shadow_stats(struct perf_stat_config *config, 63862306a36Sopenharmony_ci struct evsel *evsel, 63962306a36Sopenharmony_ci double avg, int aggr_idx, 64062306a36Sopenharmony_ci struct perf_stat_output_ctx *out, 64162306a36Sopenharmony_ci struct rblist *metric_events) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci typedef void (*stat_print_function_t)(struct perf_stat_config *config, 64462306a36Sopenharmony_ci const struct evsel *evsel, 64562306a36Sopenharmony_ci int aggr_idx, double misses, 64662306a36Sopenharmony_ci struct perf_stat_output_ctx *out); 64762306a36Sopenharmony_ci static const stat_print_function_t stat_print_function[STAT_MAX] = { 64862306a36Sopenharmony_ci [STAT_INSTRUCTIONS] = print_instructions, 64962306a36Sopenharmony_ci [STAT_BRANCH_MISS] = print_branch_miss, 65062306a36Sopenharmony_ci [STAT_L1D_MISS] = print_l1d_miss, 65162306a36Sopenharmony_ci [STAT_L1I_MISS] = print_l1i_miss, 65262306a36Sopenharmony_ci [STAT_DTLB_MISS] = print_dtlb_miss, 65362306a36Sopenharmony_ci [STAT_ITLB_MISS] = print_itlb_miss, 65462306a36Sopenharmony_ci [STAT_LL_MISS] = print_ll_miss, 65562306a36Sopenharmony_ci [STAT_CACHE_MISSES] = print_cache_miss, 65662306a36Sopenharmony_ci [STAT_STALLED_CYCLES_FRONT] = print_stalled_cycles_front, 65762306a36Sopenharmony_ci [STAT_STALLED_CYCLES_BACK] = print_stalled_cycles_back, 65862306a36Sopenharmony_ci [STAT_CYCLES] = print_cycles, 65962306a36Sopenharmony_ci [STAT_NSECS] = print_nsecs, 66062306a36Sopenharmony_ci }; 66162306a36Sopenharmony_ci print_metric_t print_metric = out->print_metric; 66262306a36Sopenharmony_ci void *ctxp = out->ctx; 66362306a36Sopenharmony_ci int num = 1; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (config->iostat_run) { 66662306a36Sopenharmony_ci iostat_print_metric(config, evsel, out); 66762306a36Sopenharmony_ci } else { 66862306a36Sopenharmony_ci stat_print_function_t fn = stat_print_function[evsel__stat_type(evsel)]; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (fn) 67162306a36Sopenharmony_ci fn(config, evsel, aggr_idx, avg, out); 67262306a36Sopenharmony_ci else { 67362306a36Sopenharmony_ci double nsecs = find_stat(evsel, aggr_idx, STAT_NSECS); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (nsecs) { 67662306a36Sopenharmony_ci char unit = ' '; 67762306a36Sopenharmony_ci char unit_buf[10] = "/sec"; 67862306a36Sopenharmony_ci double ratio = convert_unit_double(1000000000.0 * avg / nsecs, 67962306a36Sopenharmony_ci &unit); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (unit != ' ') 68262306a36Sopenharmony_ci snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); 68362306a36Sopenharmony_ci print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio); 68462306a36Sopenharmony_ci } else 68562306a36Sopenharmony_ci num = 0; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci perf_stat__print_shadow_stats_metricgroup(config, evsel, aggr_idx, 69062306a36Sopenharmony_ci &num, NULL, out, metric_events); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (num == 0) 69362306a36Sopenharmony_ci print_metric(config, ctxp, NULL, NULL, NULL, 0); 69462306a36Sopenharmony_ci} 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci/** 69762306a36Sopenharmony_ci * perf_stat__skip_metric_event - Skip the evsel in the Default metricgroup, 69862306a36Sopenharmony_ci * if it's not running or not the metric event. 69962306a36Sopenharmony_ci */ 70062306a36Sopenharmony_cibool perf_stat__skip_metric_event(struct evsel *evsel, 70162306a36Sopenharmony_ci struct rblist *metric_events, 70262306a36Sopenharmony_ci u64 ena, u64 run) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci if (!evsel->default_metricgroup) 70562306a36Sopenharmony_ci return false; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (!ena || !run) 70862306a36Sopenharmony_ci return true; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci return !metricgroup__lookup(metric_events, evsel, false); 71162306a36Sopenharmony_ci} 712