lkml.org 
[lkml]   [2023]   [Feb]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2 11/14] perf kvm: Support printing attributions for dimensions
Date
This patch adds header, entry callback and width for every dimension,
thus in TUI mode the tool can print items with the defined attributions.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
tools/perf/builtin-kvm.c | 105 +++++++++++++++++++++++++++++++++++++--
1 file changed, 102 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 741ba65bf092..a56d0983c585 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -83,8 +83,12 @@ struct kvm_hists {

struct kvm_dimension {
const char *name;
+ const char *header;
+ int width;
int64_t (*cmp)(struct perf_hpp_fmt *fmt, struct hist_entry *left,
struct hist_entry *right);
+ int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he);
};

struct kvm_fmt {
@@ -102,9 +106,32 @@ empty_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
return 0;
}

+static int fmt_width(struct perf_hpp_fmt *fmt,
+ struct perf_hpp *hpp __maybe_unused,
+ struct hists *hists __maybe_unused);
+
+static int ev_name_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct kvm_event *event;
+ int width = fmt_width(fmt, hpp, he->hists);
+ char decode[decode_str_len];
+ struct perf_kvm_stat *perf_kvm;
+
+ event = container_of(he, struct kvm_event, he);
+
+ perf_kvm = event->perf_kvm;
+ perf_kvm->events_ops->decode_key(perf_kvm, &event->key, decode);
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, decode);
+}
+
static struct kvm_dimension dim_event = {
+ .header = "Event name",
.name = "name",
.cmp = empty_cmp,
+ .entry = ev_name_entry,
+ .width = 40,
};

#define EV_METRIC_CMP(metric) \
@@ -130,29 +157,77 @@ EV_METRIC_CMP(max)
EV_METRIC_CMP(min)
EV_METRIC_CMP(mean)

+#define EV_METRIC_ENTRY(metric) \
+static int ev_entry_##metric(struct perf_hpp_fmt *fmt, \
+ struct perf_hpp *hpp, \
+ struct hist_entry *he) \
+{ \
+ struct kvm_event *event; \
+ int width = fmt_width(fmt, hpp, he->hists); \
+ struct perf_kvm_stat *perf_kvm; \
+ \
+ event = container_of(he, struct kvm_event, he); \
+ perf_kvm = event->perf_kvm; \
+ return scnprintf(hpp->buf, hpp->size, "%*lu", width, \
+ get_event_##metric(event, perf_kvm->trace_vcpu)); \
+}
+
+EV_METRIC_ENTRY(time)
+EV_METRIC_ENTRY(count)
+EV_METRIC_ENTRY(max)
+EV_METRIC_ENTRY(min)
+
static struct kvm_dimension dim_time = {
+ .header = "Time (ns)",
.name = "time",
.cmp = ev_cmp_time,
+ .entry = ev_entry_time,
+ .width = 12,
};

static struct kvm_dimension dim_count = {
+ .header = "Samples",
.name = "sample",
.cmp = ev_cmp_count,
+ .entry = ev_entry_count,
+ .width = 12,
};

static struct kvm_dimension dim_max_time = {
+ .header = "Max Time (ns)",
.name = "max_t",
.cmp = ev_cmp_max,
+ .entry = ev_entry_max,
+ .width = 14,
};

static struct kvm_dimension dim_min_time = {
+ .header = "Min Time (ns)",
.name = "min_t",
.cmp = ev_cmp_min,
+ .entry = ev_entry_min,
+ .width = 14,
};

+static int ev_entry_mean(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hist_entry *he)
+{
+ struct kvm_event *event;
+ int width = fmt_width(fmt, hpp, he->hists);
+ struct perf_kvm_stat *perf_kvm;
+
+ event = container_of(he, struct kvm_event, he);
+ perf_kvm = event->perf_kvm;
+ return scnprintf(hpp->buf, hpp->size, "%*lu", width,
+ get_event_mean(event, perf_kvm->trace_vcpu));
+}
+
static struct kvm_dimension dim_mean_time = {
+ .header = "Mean Time (ns)",
.name = "mean_t",
.cmp = ev_cmp_mean,
+ .entry = ev_entry_mean,
+ .width = 14,
};

static struct kvm_dimension *dimensions[] = {
@@ -165,6 +240,30 @@ static struct kvm_dimension *dimensions[] = {
NULL,
};

+static int fmt_width(struct perf_hpp_fmt *fmt,
+ struct perf_hpp *hpp __maybe_unused,
+ struct hists *hists __maybe_unused)
+{
+ struct kvm_fmt *kvm_fmt;
+
+ kvm_fmt = container_of(fmt, struct kvm_fmt, fmt);
+ return kvm_fmt->dim->width;
+}
+
+static int fmt_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+ struct hists *hists, int line __maybe_unused,
+ int *span __maybe_unused)
+{
+ struct kvm_fmt *kvm_fmt;
+ struct kvm_dimension *dim;
+ int width = fmt_width(fmt, hpp, hists);
+
+ kvm_fmt = container_of(fmt, struct kvm_fmt, fmt);
+ dim = kvm_fmt->dim;
+
+ return scnprintf(hpp->buf, hpp->size, "%*s", width, dim->header);
+}
+
static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
{
struct kvm_fmt *kvm_fmt_a = container_of(a, struct kvm_fmt, fmt);
@@ -214,9 +313,9 @@ static struct kvm_fmt *get_format(const char *name)
fmt->cmp = dim->cmp;
fmt->sort = dim->cmp;
fmt->color = NULL;
- fmt->entry = NULL;
- fmt->header = NULL;
- fmt->width = NULL;
+ fmt->entry = dim->entry;
+ fmt->header = fmt_header;
+ fmt->width = fmt_width;
fmt->collapse = dim->cmp;
fmt->equal = fmt_equal;
fmt->free = fmt_free;
--
2.34.1
\
 
 \ /
  Last update: 2023-03-27 00:38    [W:0.249 / U:0.288 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site