BPF List
 help / color / mirror / Atom feed
From: Leon Hwang <leon.hwang@linux.dev>
To: Puranjay Mohan <puranjay@kernel.org>, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>
Subject: Re: [PATCH bpf-next 0/4] bpf: Inline the numeric open-coded iterator kfuncs
Date: Wed, 15 Jul 2026 22:11:01 +0800	[thread overview]
Message-ID: <ffb90c46-6bb4-438f-8915-6983a931d3e1@linux.dev> (raw)
In-Reply-To: <20260715130430.318421-1-puranjay@kernel.org>

On 2026/7/15 21:04, Puranjay Mohan wrote:
> The bpf_for(i, start, end) macro is BPF's open-coded numeric iterator. It
> expands into calls to three kfuncs: bpf_iter_num_new() to set the iterator
> up, bpf_iter_num_next() once per iteration, and bpf_iter_num_destroy() to
> tear it down. The verifier emits these as ordinary kfunc calls, so a
> bpf_for() loop pays function-call overhead on setup, teardown, and — most
> importantly — on every single iteration via bpf_iter_num_next().
> 
> All three kfuncs are tiny and only touch the 8-byte on-stack iterator state
> (struct bpf_iter_num_kern { int cur; int end; }). That makes them good
> candidates for inlining, the same way several other special kfuncs are
> already open-coded in bpf_fixup_kfunc_call(). This series replaces each of
> the three calls with an equivalent inline BPF instruction sequence:
> 
>   - bpf_iter_num_new(): keeps the (s64)end - (s64)start overflow check
>     (emitted with sign-extending moves) and returns the same
>     -EINVAL / -E2BIG / 0 results as the kfunc.
> 
>   - bpf_iter_num_next(): the hot path. Since cur and end are int, the
>     kfunc's (s64)(s->cur + 1) >= s->end test reduces to a signed 32-bit
>     comparison of (s->cur + 1) against s->end, so the inlined code uses a
>     32-bit compare with no sign extension.
> 
>   - bpf_iter_num_destroy(): a single 8-byte store zeroing the state.
> 
> The emitted instructions are plain BPF and remain valid for the
> interpreter, so interpreter fallback stays correct and no jit_required
> marking is needed.
> 
> Patch 4 adds a bench_bpf_for benchmark, modeled on the existing bpf_loop
> benchmark, that runs a bpf_for() loop with an empty body so the
> per-iteration iterator cost can be measured directly.
> 
> Results (./bench -p 1 --nr_loops 1000 bpf-for):
> 
>   +--------+----------------------+----------------------+--------------+
>   |  arch  |       inlined        |     kfunc calls      |   result     |
>   +--------+----------------------+----------------------+--------------+
>   | x86-64 | 12884 M/s (0.078 ns) | 5812 M/s (0.172 ns)  | ~2.2x faster |
>   +--------+----------------------+----------------------+--------------+
>   | arm64  | 546.1 M/s (1.831 ns) | 545.8 M/s (1.832 ns) | neutral      |
>   +--------+----------------------+----------------------+--------------+
> 


The bench results are excellent on x86-64.

However, after looking through patch #1 and patch #2, hmm, they seem
quite complex.

Alexei suggested that the kfuncs could be inlined by the kernel disasm
approach [1]. With that approach, it should be possible to inline many
kfuncs and helpers on both x86-64 and arm64.

I think we should try hard to implement the disasm approach.

[1]
https://lore.kernel.org/bpf/CAADnVQLNmQGKf5S5ZNwHYzScYBhnWFmnzLg=5Xxy4SgYKE3EfQ@mail.gmail.com/

Thanks,
Leon

> On x86-64, removing the per-iteration call to bpf_iter_num_next() roughly
> doubles throughput. On arm64 the numbers are unchanged: the loop is bound
> by the load/store dependency chain on the on-stack iterator state rather
> than by call overhead, so inlining neither helps nor hurts there. It still
> removes the calls.
> 
> [...]

  parent reply	other threads:[~2026-07-15 14:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-15 13:04 [PATCH bpf-next 0/4] bpf: Inline the numeric open-coded iterator kfuncs Puranjay Mohan
2026-07-15 13:04 ` [PATCH bpf-next 1/4] bpf: Inline bpf_iter_num_new() kfunc Puranjay Mohan
2026-07-15 13:33   ` sashiko-bot
2026-07-15 13:04 ` [PATCH bpf-next 2/4] bpf: Inline bpf_iter_num_next() kfunc Puranjay Mohan
2026-07-15 13:04 ` [PATCH bpf-next 3/4] bpf: Inline bpf_iter_num_destroy() kfunc Puranjay Mohan
2026-07-15 13:04 ` [PATCH bpf-next 4/4] selftests/bpf: Add bpf_for() benchmark Puranjay Mohan
2026-07-15 14:11 ` Leon Hwang [this message]
2026-07-15 14:15   ` [PATCH bpf-next 0/4] bpf: Inline the numeric open-coded iterator kfuncs Puranjay Mohan

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=ffb90c46-6bb4-438f-8915-6983a931d3e1@linux.dev \
    --to=leon.hwang@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=puranjay@kernel.org \
    --cc=song@kernel.org \
    --cc=yonghong.song@linux.dev \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox