BPF Archive on lore.kernel.org
 help / color / Atom feed
From: "Toke Høiland-Jørgensen" <toke@redhat.com>
To: Song Liu <songliubraving@fb.com>,
	netdev@vger.kernel.org, bpf@vger.kernel.org
Cc: kernel-team@fb.com, ast@kernel.org, daniel@iogearbox.net,
	Song Liu <songliubraving@fb.com>
Subject: Re: [RFC bpf-next 3/4] bpftool: introduce "prog profile" command
Date: Thu, 13 Feb 2020 22:50:06 +0100
Message-ID: <87o8u2dunl.fsf@toke.dk> (raw)
In-Reply-To: <20200213210115.1455809-4-songliubraving@fb.com>

Song Liu <songliubraving@fb.com> writes:

> With fentry/fexit programs, it is possible to profile BPF program with
> hardware counters. Introduce bpftool "prog profile", which measures key
> metrics of a BPF program.
>
> bpftool prog profile command creates per-cpu perf events. Then it attaches
> fentry/fexit programs to the target BPF program. The fentry program saves
> perf event value to a map. The fexit program reads the perf event again,
> and calculates the difference, which is the instructions/cycles used by
> the target program.
>
> Example input and output:
>
>   ./bpftool prog profile 20 id 810 cycles instructions
>   cycles: duration 20 run_cnt 1368 miss_cnt 665
>           counter 503377 enabled 668202 running 351857
>   instructions: duration 20 run_cnt 1368 miss_cnt 707
>           counter 398625 enabled 502330 running 272014
>
> This command measures cycles and instructions for BPF program with id
> 810 for 20 seconds. The program has triggered 1368 times. cycles was not
> measured in 665 out of these runs, because of perf event multiplexing
> (some perf commands are running in the background). In these runs, the BPF
> program consumed 503377 cycles. The perf_event enabled and running time
> are 668202 and 351857 respectively.
>
> Note that, this approach measures cycles and instructions in very small
> increments. So the fentry/fexit programs introduce noticable errors to
> the measurement results.
>
> The fentry/fexit programs are generated with BPF skeleton. Currently,
> generation of the skeleton requires some manual steps.
>
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
>  tools/bpf/bpftool/profiler.skel.h         | 820 ++++++++++++++++++++++
>  tools/bpf/bpftool/prog.c                  | 387 +++++++++-
>  tools/bpf/bpftool/skeleton/README         |   3 +
>  tools/bpf/bpftool/skeleton/profiler.bpf.c | 185 +++++
>  tools/bpf/bpftool/skeleton/profiler.h     |  47 ++
>  5 files changed, 1441 insertions(+), 1 deletion(-)
>  create mode 100644 tools/bpf/bpftool/profiler.skel.h
>  create mode 100644 tools/bpf/bpftool/skeleton/README
>  create mode 100644 tools/bpf/bpftool/skeleton/profiler.bpf.c
>  create mode 100644 tools/bpf/bpftool/skeleton/profiler.h
>
> diff --git a/tools/bpf/bpftool/profiler.skel.h b/tools/bpf/bpftool/profiler.skel.h
> new file mode 100644
> index 000000000000..10e99989c03e
> --- /dev/null
> +++ b/tools/bpf/bpftool/profiler.skel.h
> @@ -0,0 +1,820 @@
> +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
> +
> +/* THIS FILE IS AUTOGENERATED! */
> +#ifndef __PROFILER_BPF_SKEL_H__
> +#define __PROFILER_BPF_SKEL_H__
> +
> +#include <stdlib.h>
> +#include <bpf/libbpf.h>
> +
> +struct profiler_bpf {
> +	struct bpf_object_skeleton *skeleton;
> +	struct bpf_object *obj;
> +	struct {
> +		struct bpf_map *events;
> +		struct bpf_map *fentry_readings;
> +		struct bpf_map *accum_readings;
> +		struct bpf_map *counts;
> +		struct bpf_map *miss_counts;
> +		struct bpf_map *rodata;
> +	} maps;
> +	struct {
> +		struct bpf_program *fentry_XXX;
> +		struct bpf_program *fexit_XXX;
> +	} progs;
> +	struct {
> +		struct bpf_link *fentry_XXX;
> +		struct bpf_link *fexit_XXX;
> +	} links;
> +	struct profiler_bpf__rodata {
> +		__u32 num_cpu;
> +		__u32 num_metric;
> +	} *rodata;
> +};
> +
> +static void
> +profiler_bpf__destroy(struct profiler_bpf *obj)
> +{
> +	if (!obj)
> +		return;
> +	if (obj->skeleton)
> +		bpf_object__destroy_skeleton(obj->skeleton);
> +	free(obj);
> +}
> +
> +static inline int
> +profiler_bpf__create_skeleton(struct profiler_bpf *obj);
> +
> +static inline struct profiler_bpf *
> +profiler_bpf__open_opts(const struct bpf_object_open_opts *opts)
> +{
> +	struct profiler_bpf *obj;
> +
> +	obj = (typeof(obj))calloc(1, sizeof(*obj));
> +	if (!obj)
> +		return NULL;
> +	if (profiler_bpf__create_skeleton(obj))
> +		goto err;
> +	if (bpf_object__open_skeleton(obj->skeleton, opts))
> +		goto err;
> +
> +	return obj;
> +err:
> +	profiler_bpf__destroy(obj);
> +	return NULL;
> +}
> +
> +static inline struct profiler_bpf *
> +profiler_bpf__open(void)
> +{
> +	return profiler_bpf__open_opts(NULL);
> +}
> +
> +static inline int
> +profiler_bpf__load(struct profiler_bpf *obj)
> +{
> +	return bpf_object__load_skeleton(obj->skeleton);
> +}
> +
> +static inline struct profiler_bpf *
> +profiler_bpf__open_and_load(void)
> +{
> +	struct profiler_bpf *obj;
> +
> +	obj = profiler_bpf__open();
> +	if (!obj)
> +		return NULL;
> +	if (profiler_bpf__load(obj)) {
> +		profiler_bpf__destroy(obj);
> +		return NULL;
> +	}
> +	return obj;
> +}
> +
> +static inline int
> +profiler_bpf__attach(struct profiler_bpf *obj)
> +{
> +	return bpf_object__attach_skeleton(obj->skeleton);
> +}
> +
> +static inline void
> +profiler_bpf__detach(struct profiler_bpf *obj)
> +{
> +	return bpf_object__detach_skeleton(obj->skeleton);
> +}
> +
> +static inline int
> +profiler_bpf__create_skeleton(struct profiler_bpf *obj)
> +{
> +	struct bpf_object_skeleton *s;
> +
> +	s = (typeof(s))calloc(1, sizeof(*s));
> +	if (!s)
> +		return -1;
> +	obj->skeleton = s;
> +
> +	s->sz = sizeof(*s);
> +	s->name = "profiler_bpf";
> +	s->obj = &obj->obj;
> +
> +	/* maps */
> +	s->map_cnt = 6;
> +	s->map_skel_sz = sizeof(*s->maps);
> +	s->maps = (typeof(s->maps))calloc(s->map_cnt, s->map_skel_sz);
> +	if (!s->maps)
> +		goto err;
> +
> +	s->maps[0].name = "events";
> +	s->maps[0].map = &obj->maps.events;
> +
> +	s->maps[1].name = "fentry_readings";
> +	s->maps[1].map = &obj->maps.fentry_readings;
> +
> +	s->maps[2].name = "accum_readings";
> +	s->maps[2].map = &obj->maps.accum_readings;
> +
> +	s->maps[3].name = "counts";
> +	s->maps[3].map = &obj->maps.counts;
> +
> +	s->maps[4].name = "miss_counts";
> +	s->maps[4].map = &obj->maps.miss_counts;
> +
> +	s->maps[5].name = "profiler.rodata";
> +	s->maps[5].map = &obj->maps.rodata;
> +	s->maps[5].mmaped = (void **)&obj->rodata;
> +
> +	/* programs */
> +	s->prog_cnt = 2;
> +	s->prog_skel_sz = sizeof(*s->progs);
> +	s->progs = (typeof(s->progs))calloc(s->prog_cnt, s->prog_skel_sz);
> +	if (!s->progs)
> +		goto err;
> +
> +	s->progs[0].name = "fentry_XXX";
> +	s->progs[0].prog = &obj->progs.fentry_XXX;
> +	s->progs[0].link = &obj->links.fentry_XXX;
> +
> +	s->progs[1].name = "fexit_XXX";
> +	s->progs[1].prog = &obj->progs.fexit_XXX;
> +	s->progs[1].link = &obj->links.fexit_XXX;
> +
> +	s->data_sz = 18256;
> +	s->data = (void *)"\
> +\x7f\x45\x4c\x46\x02\x01\x01\0\0\0\0\0\0\0\0\0\x01\0\xf7\0\x01\0\0\0\0\0\0\0\0\

Holy binary blob, Batman! :)

What is this blob, exactly? The bytecode output of a precompiled
program?

-Toke


  reply index

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-13 21:01 [RFC bpf-next 0/4] bpftool: introduce prog profile Song Liu
2020-02-13 21:01 ` [RFC bpf-next 1/4] bpf: allow bpf_perf_event_read_value in all BPF programs Song Liu
2020-02-13 21:01 ` [RFC bpf-next 2/4] libbpf: introduce bpf_program__overwrite_section_name() Song Liu
2020-02-13 21:01 ` [RFC bpf-next 3/4] bpftool: introduce "prog profile" command Song Liu
2020-02-13 21:50   ` Toke Høiland-Jørgensen [this message]
2020-02-13 21:55     ` Song Liu
2020-02-13 22:06       ` Toke Høiland-Jørgensen
2020-02-15  0:45   ` Alexei Starovoitov
2020-02-17  2:51     ` Song Liu
2020-02-13 21:01 ` [RFC bpf-next 4/4] bpftool: Documentation for bpftool prog profile Song Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o8u2dunl.fsf@toke.dk \
    --to=toke@redhat.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@fb.com \
    --cc=netdev@vger.kernel.org \
    --cc=songliubraving@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

BPF Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/bpf/0 bpf/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 bpf bpf/ https://lore.kernel.org/bpf \
		bpf@vger.kernel.org
	public-inbox-index bpf

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.bpf


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git