Commit 42e1fd80 authored by Alexey Budankov's avatar Alexey Budankov Committed by Arnaldo Carvalho de Melo

perf record: Implement COMPRESSED event record and its attributes

Implemented PERF_RECORD_COMPRESSED event, related data types, header
feature and functions to write, read and print feature attributes from
the trace header section.

comp_mmap_len preserves the size of mmaped kernel buffer that was used
during collection. comp_mmap_len size is used on loading stage as the
size of decomp buffer for decompression of COMPRESSED events content.

Committer notes:

Fixed up conflict with BPF_PROG_INFO and BTF_BTF header features.
Signed-off-by: default avatarAlexey Budankov <alexey.budankov@linux.intel.com>
Reviewed-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/ebbaf031-8dda-3864-ebc6-7922d43ee515@linux.intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d3c8c08e
......@@ -272,6 +272,19 @@ struct {
Two uint64_t for the time of first sample and the time of last sample.
HEADER_COMPRESSED = 27,
struct {
u32 version;
u32 type;
u32 level;
u32 ratio;
u32 mmap_len;
};
Indicates that trace contains records of PERF_RECORD_COMPRESSED type
that have perf_events records in compressed form.
other bits are reserved and should ignored for now
HEADER_FEAT_BITS = 256,
......@@ -437,6 +450,17 @@ struct auxtrace_error_event {
Describes a header feature. These are records used in pipe-mode that
contain information that otherwise would be in perf.data file's header.
PERF_RECORD_COMPRESSED = 81,
struct compressed_event {
struct perf_event_header header;
char data[];
};
The header is followed by compressed data frame that can be decompressed
into array of perf trace records. The size of the entire compressed event
record including the header is limited by the max value of header.size.
Event types
Define the event attributes with their IDs.
......
......@@ -372,6 +372,11 @@ static int record__mmap_flush_parse(const struct option *opt,
return 0;
}
static int record__comp_enabled(struct record *rec)
{
return rec->opts.comp_level > 0;
}
static int process_synthesized_event(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
......@@ -888,6 +893,8 @@ static void record__init_features(struct record *rec)
perf_header__clear_feat(&session->header, HEADER_CLOCKID);
perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
if (!record__comp_enabled(rec))
perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
perf_header__clear_feat(&session->header, HEADER_STAT);
}
......@@ -1245,6 +1252,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
err = -1;
goto out_child;
}
session->header.env.comp_mmap_len = session->evlist->mmap_len;
err = bpf__apply_obj_config();
if (err) {
......
......@@ -86,6 +86,7 @@ struct record_opts {
int nr_cblocks;
int affinity;
int mmap_flush;
unsigned int comp_level;
};
enum perf_affinity {
......
......@@ -63,6 +63,10 @@ struct perf_env {
struct cpu_cache_level *caches;
int caches_cnt;
u32 comp_ratio;
u32 comp_ver;
u32 comp_type;
u32 comp_level;
u32 comp_mmap_len;
struct numa_node *numa_nodes;
struct memory_node *memory_nodes;
unsigned long long memory_bsize;
......@@ -81,6 +85,12 @@ struct perf_env {
} bpf_progs;
};
enum perf_compress_type {
PERF_COMP_NONE = 0,
PERF_COMP_ZSTD,
PERF_COMP_MAX
};
struct bpf_prog_info_node;
struct btf_node;
......
......@@ -68,6 +68,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
[PERF_RECORD_TIME_CONV] = "TIME_CONV",
[PERF_RECORD_HEADER_FEATURE] = "FEATURE",
[PERF_RECORD_COMPRESSED] = "COMPRESSED",
};
static const char *perf_ns__names[] = {
......
......@@ -255,6 +255,7 @@ enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_EVENT_UPDATE = 78,
PERF_RECORD_TIME_CONV = 79,
PERF_RECORD_HEADER_FEATURE = 80,
PERF_RECORD_COMPRESSED = 81,
PERF_RECORD_HEADER_MAX
};
......@@ -627,6 +628,11 @@ struct feature_event {
char data[];
};
struct compressed_event {
struct perf_event_header header;
char data[];
};
union perf_event {
struct perf_event_header header;
struct mmap_event mmap;
......@@ -660,6 +666,7 @@ union perf_event {
struct feature_event feat;
struct ksymbol_event ksymbol_event;
struct bpf_event bpf_event;
struct compressed_event pack;
};
void perf_event__print_totals(void);
......
......@@ -1344,6 +1344,30 @@ static int write_mem_topology(struct feat_fd *ff __maybe_unused,
return ret;
}
static int write_compressed(struct feat_fd *ff __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
int ret;
ret = do_write(ff, &(ff->ph->env.comp_ver), sizeof(ff->ph->env.comp_ver));
if (ret)
return ret;
ret = do_write(ff, &(ff->ph->env.comp_type), sizeof(ff->ph->env.comp_type));
if (ret)
return ret;
ret = do_write(ff, &(ff->ph->env.comp_level), sizeof(ff->ph->env.comp_level));
if (ret)
return ret;
ret = do_write(ff, &(ff->ph->env.comp_ratio), sizeof(ff->ph->env.comp_ratio));
if (ret)
return ret;
return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len));
}
static void print_hostname(struct feat_fd *ff, FILE *fp)
{
fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
......@@ -1688,6 +1712,13 @@ static void print_cache(struct feat_fd *ff, FILE *fp __maybe_unused)
}
}
static void print_compressed(struct feat_fd *ff, FILE *fp)
{
fprintf(fp, "# compressed : %s, level = %d, ratio = %d\n",
ff->ph->env.comp_type == PERF_COMP_ZSTD ? "Zstd" : "Unknown",
ff->ph->env.comp_level, ff->ph->env.comp_ratio);
}
static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
{
const char *delimiter = "# pmu mappings: ";
......@@ -2667,6 +2698,27 @@ static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
return err;
}
static int process_compressed(struct feat_fd *ff,
void *data __maybe_unused)
{
if (do_read_u32(ff, &(ff->ph->env.comp_ver)))
return -1;
if (do_read_u32(ff, &(ff->ph->env.comp_type)))
return -1;
if (do_read_u32(ff, &(ff->ph->env.comp_level)))
return -1;
if (do_read_u32(ff, &(ff->ph->env.comp_ratio)))
return -1;
if (do_read_u32(ff, &(ff->ph->env.comp_mmap_len)))
return -1;
return 0;
}
struct feature_ops {
int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
void (*print)(struct feat_fd *ff, FILE *fp);
......@@ -2730,6 +2782,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPN(DIR_FORMAT, dir_format, false),
FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false),
FEAT_OPR(BPF_BTF, bpf_btf, false),
FEAT_OPR(COMPRESSED, compressed, false),
};
struct header_print_data {
......
......@@ -42,6 +42,7 @@ enum {
HEADER_DIR_FORMAT,
HEADER_BPF_PROG_INFO,
HEADER_BPF_BTF,
HEADER_COMPRESSED,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment