• Eduard Zingerman's avatar
    selftests/bpf: fix bpf_loop_bench for new callback verification scheme · f40bfd16
    Eduard Zingerman authored
    This is a preparatory change. A follow-up patch "bpf: verify callbacks
    as if they are called unknown number of times" changes logic for
    callbacks handling. While previously callbacks were verified as a
    single function call, new scheme takes into account that callbacks
    could be executed unknown number of times.
    
    This has dire implications for bpf_loop_bench:
    
        SEC("fentry/" SYS_PREFIX "sys_getpgid")
        int benchmark(void *ctx)
        {
                for (int i = 0; i < 1000; i++) {
                        bpf_loop(nr_loops, empty_callback, NULL, 0);
                        __sync_add_and_fetch(&hits, nr_loops);
                }
                return 0;
        }
    
    W/o callbacks change verifier sees it as a 1000 calls to
    empty_callback(). However, with callbacks change things become
    exponential:
    - i=0: state exploring empty_callback is scheduled with i=0 (a);
    - i=1: state exploring empty_callback is scheduled with i=1;
      ...
    - i=999: state exploring empty_callback is scheduled with i=999;
    - state (a) is popped from stack;
    - i=1: state exploring empty_callback is scheduled with i=1;
      ...
    
    Avoid this issue by rewriting outer loop as bpf_loop().
    Unfortunately, this adds a function call to a loop at runtime, which
    negatively affects performance:
    
                throughput               latency
       before:  149.919 ± 0.168 M ops/s, 6.670 ns/op
       after :  137.040 ± 0.187 M ops/s, 7.297 ns/op
    Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
    Signed-off-by: default avatarEduard Zingerman <eddyz87@gmail.com>
    Link: https://lore.kernel.org/r/20231121020701.26440-4-eddyz87@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    f40bfd16
bpf_loop_bench.c 545 Bytes