mirror of
https://github.com/torvalds/linux.git
synced 2026-10-16 21:00:02 +02:00
Add a reusable timing library for BPF benchmarks that need to measure BPF program execution time. The BPF side (progs/bench_bpf_timing.bpf.h) provides per-CPU sample arrays and BENCH_BPF_LOOP(), a macro that brackets batch_iters iterations with bpf_ktime_get_ns() reads and records the elapsed time. One extra untimed iteration runs afterward for output validation. The userspace side (benchs/bench_bpf_timing.c) collects samples from the skeleton BSS, computes percentile statistics, and auto-calibrates batch_iters to target ~10 ms per batch. Signed-off-by: Puranjay Mohan <puranjay@kernel.org> Link: https://lore.kernel.org/r/20260427232313.1582588-3-puranjay@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
70 lines
1.7 KiB
C
70 lines
1.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
|
|
|
|
#ifndef __BENCH_BPF_TIMING_BPF_H__
|
|
#define __BENCH_BPF_TIMING_BPF_H__
|
|
|
|
#include <stdbool.h>
|
|
#include <linux/bpf.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf_may_goto.h>
|
|
|
|
#ifndef BENCH_NR_SAMPLES
|
|
#define BENCH_NR_SAMPLES 4096
|
|
#endif
|
|
#ifndef BENCH_NR_CPUS
|
|
#define BENCH_NR_CPUS 256
|
|
#endif
|
|
#define BENCH_CPU_MASK (BENCH_NR_CPUS - 1)
|
|
|
|
__u64 timing_samples[BENCH_NR_CPUS][BENCH_NR_SAMPLES];
|
|
__u32 timing_idx[BENCH_NR_CPUS];
|
|
|
|
volatile __u32 batch_iters;
|
|
volatile __u32 timing_enabled;
|
|
|
|
static __always_inline void bench_record_sample(__u64 elapsed_ns)
|
|
{
|
|
__u32 cpu, idx;
|
|
|
|
if (!timing_enabled)
|
|
return;
|
|
|
|
cpu = bpf_get_smp_processor_id() & BENCH_CPU_MASK;
|
|
idx = timing_idx[cpu];
|
|
|
|
if (idx >= BENCH_NR_SAMPLES)
|
|
return;
|
|
|
|
timing_samples[cpu][idx] = elapsed_ns;
|
|
timing_idx[cpu] = idx + 1;
|
|
}
|
|
|
|
/*
|
|
* @body: expression to time; return value (int) stored in __bench_result.
|
|
* @reset: undo body's side-effects so each iteration starts identically.
|
|
* May reference __bench_result. Use ({}) for empty reset.
|
|
*
|
|
* Runs batch_iters timed iterations, then one untimed iteration whose
|
|
* return value the macro evaluates to (for validation).
|
|
*/
|
|
#define BENCH_BPF_LOOP(body, reset) ({ \
|
|
__u64 __bench_start = bpf_ktime_get_ns(); \
|
|
__u32 __bench_i; \
|
|
int __bench_result; \
|
|
\
|
|
for (__bench_i = 0; \
|
|
__bench_i < batch_iters && can_loop; \
|
|
__bench_i++) { \
|
|
__bench_result = (body); \
|
|
reset; \
|
|
} \
|
|
\
|
|
bench_record_sample(bpf_ktime_get_ns() - __bench_start); \
|
|
\
|
|
__bench_result = (body); \
|
|
__bench_result; \
|
|
})
|
|
|
|
#endif /* __BENCH_BPF_TIMING_BPF_H__ */
|