1*08158c11SPuranjay Mohan /* SPDX-License-Identifier: GPL-2.0 */ 2*08158c11SPuranjay Mohan /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 3*08158c11SPuranjay Mohan 4*08158c11SPuranjay Mohan #ifndef __BENCH_BPF_TIMING_BPF_H__ 5*08158c11SPuranjay Mohan #define __BENCH_BPF_TIMING_BPF_H__ 6*08158c11SPuranjay Mohan 7*08158c11SPuranjay Mohan #include <stdbool.h> 8*08158c11SPuranjay Mohan #include <linux/bpf.h> 9*08158c11SPuranjay Mohan #include <bpf/bpf_helpers.h> 10*08158c11SPuranjay Mohan #include <bpf_may_goto.h> 11*08158c11SPuranjay Mohan 12*08158c11SPuranjay Mohan #ifndef BENCH_NR_SAMPLES 13*08158c11SPuranjay Mohan #define BENCH_NR_SAMPLES 4096 14*08158c11SPuranjay Mohan #endif 15*08158c11SPuranjay Mohan #ifndef BENCH_NR_CPUS 16*08158c11SPuranjay Mohan #define BENCH_NR_CPUS 256 17*08158c11SPuranjay Mohan #endif 18*08158c11SPuranjay Mohan #define BENCH_CPU_MASK (BENCH_NR_CPUS - 1) 19*08158c11SPuranjay Mohan 20*08158c11SPuranjay Mohan __u64 timing_samples[BENCH_NR_CPUS][BENCH_NR_SAMPLES]; 21*08158c11SPuranjay Mohan __u32 timing_idx[BENCH_NR_CPUS]; 22*08158c11SPuranjay Mohan 23*08158c11SPuranjay Mohan volatile __u32 batch_iters; 24*08158c11SPuranjay Mohan volatile __u32 timing_enabled; 25*08158c11SPuranjay Mohan 26*08158c11SPuranjay Mohan static __always_inline void bench_record_sample(__u64 elapsed_ns) 27*08158c11SPuranjay Mohan { 28*08158c11SPuranjay Mohan __u32 cpu, idx; 29*08158c11SPuranjay Mohan 30*08158c11SPuranjay Mohan if (!timing_enabled) 31*08158c11SPuranjay Mohan return; 32*08158c11SPuranjay Mohan 33*08158c11SPuranjay Mohan cpu = bpf_get_smp_processor_id() & BENCH_CPU_MASK; 34*08158c11SPuranjay Mohan idx = timing_idx[cpu]; 35*08158c11SPuranjay Mohan 36*08158c11SPuranjay Mohan if (idx >= BENCH_NR_SAMPLES) 37*08158c11SPuranjay Mohan return; 38*08158c11SPuranjay Mohan 39*08158c11SPuranjay Mohan timing_samples[cpu][idx] = elapsed_ns; 40*08158c11SPuranjay Mohan timing_idx[cpu] = idx + 1; 41*08158c11SPuranjay Mohan } 42*08158c11SPuranjay Mohan 43*08158c11SPuranjay Mohan /* 44*08158c11SPuranjay Mohan * @body: expression to time; return value (int) stored in __bench_result. 45*08158c11SPuranjay Mohan * @reset: undo body's side-effects so each iteration starts identically. 46*08158c11SPuranjay Mohan * May reference __bench_result. Use ({}) for empty reset. 47*08158c11SPuranjay Mohan * 48*08158c11SPuranjay Mohan * Runs batch_iters timed iterations, then one untimed iteration whose 49*08158c11SPuranjay Mohan * return value the macro evaluates to (for validation). 50*08158c11SPuranjay Mohan */ 51*08158c11SPuranjay Mohan #define BENCH_BPF_LOOP(body, reset) ({ \ 52*08158c11SPuranjay Mohan __u64 __bench_start = bpf_ktime_get_ns(); \ 53*08158c11SPuranjay Mohan __u32 __bench_i; \ 54*08158c11SPuranjay Mohan int __bench_result; \ 55*08158c11SPuranjay Mohan \ 56*08158c11SPuranjay Mohan for (__bench_i = 0; \ 57*08158c11SPuranjay Mohan __bench_i < batch_iters && can_loop; \ 58*08158c11SPuranjay Mohan __bench_i++) { \ 59*08158c11SPuranjay Mohan __bench_result = (body); \ 60*08158c11SPuranjay Mohan reset; \ 61*08158c11SPuranjay Mohan } \ 62*08158c11SPuranjay Mohan \ 63*08158c11SPuranjay Mohan bench_record_sample(bpf_ktime_get_ns() - __bench_start); \ 64*08158c11SPuranjay Mohan \ 65*08158c11SPuranjay Mohan __bench_result = (body); \ 66*08158c11SPuranjay Mohan __bench_result; \ 67*08158c11SPuranjay Mohan }) 68*08158c11SPuranjay Mohan 69*08158c11SPuranjay Mohan #endif /* __BENCH_BPF_TIMING_BPF_H__ */ 70