Skip to content

Commit 737433c

Browse files
mflemingAlexei Starovoitov
authored andcommitted
selftests/bpf: Add LPM trie microbenchmarks
Add benchmarks for the standard set of operations: LOOKUP, INSERT, UPDATE, DELETE. Also include benchmarks to measure the overhead of the bench framework itself (NOOP) as well as the overhead of generating keys (BASELINE). Lastly, this includes a benchmark for FREE (trie_free()) which is known to have terrible performance for maps with many entries. Benchmarks operate on tries without gaps in the key range, i.e. each test begins or ends with a trie with valid keys in the range [0, nr_entries). This is intended to cause maximum branching when traversing the trie. LOOKUP, UPDATE, DELETE, and FREE fill a BPF LPM trie from userspace using bpf_map_update_batch() and run the corresponding benchmark operation via bpf_loop(). INSERT starts with an empty map and fills it kernel-side from bpf_loop(). FREE records the time to free a filled LPM trie by attaching and destroying a BPF prog. NOOP measures the overhead of the test harness by running an empty function with bpf_loop(). BASELINE is similar to NOOP except that the function generates a key. Each operation runs 10,000 times using bpf_loop(). Note that this value is intentionally independent of the number of entries in the LPM trie so that the stability of the results isn't affected by the number of entries. For those benchmarks that need to reset the LPM trie once it's full (INSERT) or empty (DELETE), throughput and latency results are scaled by the fraction of a second the operation actually ran to ignore any time spent reinitialising the trie. By default, benchmarks run using sequential keys in the range [0, nr_entries). BASELINE, LOOKUP, and UPDATE can use random keys via the --random parameter but beware there is a runtime cost involved in generating random keys. Other benchmarks are prohibited from using random keys because it can skew the results, e.g. when inserting an existing key or deleting a missing one. All measurements are recorded from within the kernel to eliminate syscall overhead. Most benchmarks run an XDP program to generate stats but FREE needs to collect latencies using fentry/fexit on map_free_deferred() because it's not possible to use fentry directly on lpm_trie.c since commit c83508d ("bpf: Avoid deadlock caused by nested kprobe and fentry bpf programs") and there's no way to create/destroy a map from within an XDP program. Here is example output from an AMD EPYC 9684X 96-Core machine for each of the benchmarks using a trie with 10K entries and a 32-bit prefix length, e.g. $ ./bench lpm-trie-$op \ --prefix_len=32 \ --producers=1 \ --nr_entries=10000 noop: throughput 74.417 ± 0.032 M ops/s ( 74.417M ops/prod), latency 13.438 ns/op baseline: throughput 70.107 ± 0.171 M ops/s ( 70.107M ops/prod), latency 14.264 ns/op lookup: throughput 8.467 ± 0.047 M ops/s ( 8.467M ops/prod), latency 118.109 ns/op insert: throughput 2.440 ± 0.015 M ops/s ( 2.440M ops/prod), latency 409.290 ns/op update: throughput 2.806 ± 0.042 M ops/s ( 2.806M ops/prod), latency 356.322 ns/op delete: throughput 4.625 ± 0.011 M ops/s ( 4.625M ops/prod), latency 215.613 ns/op free: throughput 0.578 ± 0.006 K ops/s ( 0.578K ops/prod), latency 1.730 ms/op And the same benchmarks using random keys: $ ./bench lpm-trie-$op \ --prefix_len=32 \ --producers=1 \ --nr_entries=10000 \ --random noop: throughput 74.259 ± 0.335 M ops/s ( 74.259M ops/prod), latency 13.466 ns/op baseline: throughput 35.150 ± 0.144 M ops/s ( 35.150M ops/prod), latency 28.450 ns/op lookup: throughput 7.119 ± 0.048 M ops/s ( 7.119M ops/prod), latency 140.469 ns/op insert: N/A update: throughput 2.736 ± 0.012 M ops/s ( 2.736M ops/prod), latency 365.523 ns/op delete: N/A free: N/A Signed-off-by: Matt Fleming <[email protected]> Signed-off-by: Jesper Dangaard Brouer <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent bd27626 commit 737433c

File tree

7 files changed

+853
-0
lines changed

7 files changed

+853
-0
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ $(OUTPUT)/bench_bpf_hashmap_lookup.o: $(OUTPUT)/bpf_hashmap_lookup.skel.h
816816
$(OUTPUT)/bench_htab_mem.o: $(OUTPUT)/htab_mem_bench.skel.h
817817
$(OUTPUT)/bench_bpf_crypto.o: $(OUTPUT)/crypto_bench.skel.h
818818
$(OUTPUT)/bench_sockmap.o: $(OUTPUT)/bench_sockmap_prog.skel.h
819+
$(OUTPUT)/bench_lpm_trie_map.o: $(OUTPUT)/lpm_trie_bench.skel.h $(OUTPUT)/lpm_trie_map.skel.h
819820
$(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)
820821
$(OUTPUT)/bench: LDLIBS += -lm
821822
$(OUTPUT)/bench: $(OUTPUT)/bench.o \
@@ -837,6 +838,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
837838
$(OUTPUT)/bench_htab_mem.o \
838839
$(OUTPUT)/bench_bpf_crypto.o \
839840
$(OUTPUT)/bench_sockmap.o \
841+
$(OUTPUT)/bench_lpm_trie_map.o \
840842
#
841843
$(call msg,BINARY,,$@)
842844
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@

tools/testing/selftests/bpf/bench.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ extern struct argp bench_htab_mem_argp;
284284
extern struct argp bench_trigger_batch_argp;
285285
extern struct argp bench_crypto_argp;
286286
extern struct argp bench_sockmap_argp;
287+
extern struct argp bench_lpm_trie_map_argp;
287288

288289
static const struct argp_child bench_parsers[] = {
289290
{ &bench_ringbufs_argp, 0, "Ring buffers benchmark", 0 },
@@ -299,6 +300,7 @@ static const struct argp_child bench_parsers[] = {
299300
{ &bench_trigger_batch_argp, 0, "BPF triggering benchmark", 0 },
300301
{ &bench_crypto_argp, 0, "bpf crypto benchmark", 0 },
301302
{ &bench_sockmap_argp, 0, "bpf sockmap benchmark", 0 },
303+
{ &bench_lpm_trie_map_argp, 0, "LPM trie map benchmark", 0 },
302304
{},
303305
};
304306

@@ -558,6 +560,13 @@ extern const struct bench bench_htab_mem;
558560
extern const struct bench bench_crypto_encrypt;
559561
extern const struct bench bench_crypto_decrypt;
560562
extern const struct bench bench_sockmap;
563+
extern const struct bench bench_lpm_trie_noop;
564+
extern const struct bench bench_lpm_trie_baseline;
565+
extern const struct bench bench_lpm_trie_lookup;
566+
extern const struct bench bench_lpm_trie_insert;
567+
extern const struct bench bench_lpm_trie_update;
568+
extern const struct bench bench_lpm_trie_delete;
569+
extern const struct bench bench_lpm_trie_free;
561570

562571
static const struct bench *benchs[] = {
563572
&bench_count_global,
@@ -625,6 +634,13 @@ static const struct bench *benchs[] = {
625634
&bench_crypto_encrypt,
626635
&bench_crypto_decrypt,
627636
&bench_sockmap,
637+
&bench_lpm_trie_noop,
638+
&bench_lpm_trie_baseline,
639+
&bench_lpm_trie_lookup,
640+
&bench_lpm_trie_insert,
641+
&bench_lpm_trie_update,
642+
&bench_lpm_trie_delete,
643+
&bench_lpm_trie_free,
628644
};
629645

630646
static void find_benchmark(void)

tools/testing/selftests/bpf/bench.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct bench_res {
4646
unsigned long gp_ns;
4747
unsigned long gp_ct;
4848
unsigned int stime;
49+
unsigned long duration_ns;
4950
};
5051

5152
struct bench {

0 commit comments

Comments
 (0)