Skip to content

Commit 26e9093

Browse files
4astdavem330
authored andcommitted
samples/bpf: add map performance test
performance tests for hash map and per-cpu hash map with and without pre-allocation Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7dcc42b commit 26e9093

File tree

3 files changed

+259
-0
lines changed

3 files changed

+259
-0
lines changed

samples/bpf/Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ hostprogs-y += trace_output
1818
hostprogs-y += lathist
1919
hostprogs-y += offwaketime
2020
hostprogs-y += spintest
21+
hostprogs-y += map_perf_test
2122

2223
test_verifier-objs := test_verifier.o libbpf.o
2324
test_maps-objs := test_maps.o libbpf.o
@@ -36,6 +37,7 @@ trace_output-objs := bpf_load.o libbpf.o trace_output_user.o
3637
lathist-objs := bpf_load.o libbpf.o lathist_user.o
3738
offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o
3839
spintest-objs := bpf_load.o libbpf.o spintest_user.o
40+
map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
3941

4042
# Tell kbuild to always build the programs
4143
always := $(hostprogs-y)
@@ -53,6 +55,7 @@ always += tcbpf1_kern.o
5355
always += lathist_kern.o
5456
always += offwaketime_kern.o
5557
always += spintest_kern.o
58+
always += map_perf_test_kern.o
5659

5760
HOSTCFLAGS += -I$(objtree)/usr/include
5861

@@ -71,6 +74,7 @@ HOSTLOADLIBES_trace_output += -lelf -lrt
7174
HOSTLOADLIBES_lathist += -lelf
7275
HOSTLOADLIBES_offwaketime += -lelf
7376
HOSTLOADLIBES_spintest += -lelf
77+
HOSTLOADLIBES_map_perf_test += -lelf -lrt
7478

7579
# point this to your LLVM backend with bpf support
7680
LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc

samples/bpf/map_perf_test_kern.c

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* Copyright (c) 2016 Facebook
2+
*
3+
* This program is free software; you can redistribute it and/or
4+
* modify it under the terms of version 2 of the GNU General Public
5+
* License as published by the Free Software Foundation.
6+
*/
7+
#include <linux/skbuff.h>
8+
#include <linux/netdevice.h>
9+
#include <linux/version.h>
10+
#include <uapi/linux/bpf.h>
11+
#include "bpf_helpers.h"
12+
13+
#define MAX_ENTRIES 1000
14+
15+
struct bpf_map_def SEC("maps") hash_map = {
16+
.type = BPF_MAP_TYPE_HASH,
17+
.key_size = sizeof(u32),
18+
.value_size = sizeof(long),
19+
.max_entries = MAX_ENTRIES,
20+
};
21+
22+
struct bpf_map_def SEC("maps") percpu_hash_map = {
23+
.type = BPF_MAP_TYPE_PERCPU_HASH,
24+
.key_size = sizeof(u32),
25+
.value_size = sizeof(long),
26+
.max_entries = MAX_ENTRIES,
27+
};
28+
29+
struct bpf_map_def SEC("maps") hash_map_alloc = {
30+
.type = BPF_MAP_TYPE_HASH,
31+
.key_size = sizeof(u32),
32+
.value_size = sizeof(long),
33+
.max_entries = MAX_ENTRIES,
34+
.map_flags = BPF_F_NO_PREALLOC,
35+
};
36+
37+
struct bpf_map_def SEC("maps") percpu_hash_map_alloc = {
38+
.type = BPF_MAP_TYPE_PERCPU_HASH,
39+
.key_size = sizeof(u32),
40+
.value_size = sizeof(long),
41+
.max_entries = MAX_ENTRIES,
42+
.map_flags = BPF_F_NO_PREALLOC,
43+
};
44+
45+
SEC("kprobe/sys_getuid")
46+
int stress_hmap(struct pt_regs *ctx)
47+
{
48+
u32 key = bpf_get_current_pid_tgid();
49+
long init_val = 1;
50+
long *value;
51+
52+
bpf_map_update_elem(&hash_map, &key, &init_val, BPF_ANY);
53+
value = bpf_map_lookup_elem(&hash_map, &key);
54+
if (value)
55+
bpf_map_delete_elem(&hash_map, &key);
56+
return 0;
57+
}
58+
59+
SEC("kprobe/sys_geteuid")
60+
int stress_percpu_hmap(struct pt_regs *ctx)
61+
{
62+
u32 key = bpf_get_current_pid_tgid();
63+
long init_val = 1;
64+
long *value;
65+
66+
bpf_map_update_elem(&percpu_hash_map, &key, &init_val, BPF_ANY);
67+
value = bpf_map_lookup_elem(&percpu_hash_map, &key);
68+
if (value)
69+
bpf_map_delete_elem(&percpu_hash_map, &key);
70+
return 0;
71+
}
72+
SEC("kprobe/sys_getgid")
73+
int stress_hmap_alloc(struct pt_regs *ctx)
74+
{
75+
u32 key = bpf_get_current_pid_tgid();
76+
long init_val = 1;
77+
long *value;
78+
79+
bpf_map_update_elem(&hash_map_alloc, &key, &init_val, BPF_ANY);
80+
value = bpf_map_lookup_elem(&hash_map_alloc, &key);
81+
if (value)
82+
bpf_map_delete_elem(&hash_map_alloc, &key);
83+
return 0;
84+
}
85+
86+
SEC("kprobe/sys_getegid")
87+
int stress_percpu_hmap_alloc(struct pt_regs *ctx)
88+
{
89+
u32 key = bpf_get_current_pid_tgid();
90+
long init_val = 1;
91+
long *value;
92+
93+
bpf_map_update_elem(&percpu_hash_map_alloc, &key, &init_val, BPF_ANY);
94+
value = bpf_map_lookup_elem(&percpu_hash_map_alloc, &key);
95+
if (value)
96+
bpf_map_delete_elem(&percpu_hash_map_alloc, &key);
97+
return 0;
98+
}
99+
char _license[] SEC("license") = "GPL";
100+
u32 _version SEC("version") = LINUX_VERSION_CODE;

samples/bpf/map_perf_test_user.c

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/* Copyright (c) 2016 Facebook
2+
*
3+
* This program is free software; you can redistribute it and/or
4+
* modify it under the terms of version 2 of the GNU General Public
5+
* License as published by the Free Software Foundation.
6+
*/
7+
#define _GNU_SOURCE
8+
#include <sched.h>
9+
#include <stdio.h>
10+
#include <sys/types.h>
11+
#include <asm/unistd.h>
12+
#include <unistd.h>
13+
#include <assert.h>
14+
#include <sys/wait.h>
15+
#include <stdlib.h>
16+
#include <signal.h>
17+
#include <linux/bpf.h>
18+
#include <string.h>
19+
#include <time.h>
20+
#include "libbpf.h"
21+
#include "bpf_load.h"
22+
23+
#define MAX_CNT 1000000
24+
25+
static __u64 time_get_ns(void)
26+
{
27+
struct timespec ts;
28+
29+
clock_gettime(CLOCK_MONOTONIC, &ts);
30+
return ts.tv_sec * 1000000000ull + ts.tv_nsec;
31+
}
32+
33+
#define HASH_PREALLOC (1 << 0)
34+
#define PERCPU_HASH_PREALLOC (1 << 1)
35+
#define HASH_KMALLOC (1 << 2)
36+
#define PERCPU_HASH_KMALLOC (1 << 3)
37+
38+
static int test_flags = ~0;
39+
40+
static void test_hash_prealloc(int cpu)
41+
{
42+
__u64 start_time;
43+
int i;
44+
45+
start_time = time_get_ns();
46+
for (i = 0; i < MAX_CNT; i++)
47+
syscall(__NR_getuid);
48+
printf("%d:hash_map_perf pre-alloc %lld events per sec\n",
49+
cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
50+
}
51+
52+
static void test_percpu_hash_prealloc(int cpu)
53+
{
54+
__u64 start_time;
55+
int i;
56+
57+
start_time = time_get_ns();
58+
for (i = 0; i < MAX_CNT; i++)
59+
syscall(__NR_geteuid);
60+
printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n",
61+
cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
62+
}
63+
64+
static void test_hash_kmalloc(int cpu)
65+
{
66+
__u64 start_time;
67+
int i;
68+
69+
start_time = time_get_ns();
70+
for (i = 0; i < MAX_CNT; i++)
71+
syscall(__NR_getgid);
72+
printf("%d:hash_map_perf kmalloc %lld events per sec\n",
73+
cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
74+
}
75+
76+
static void test_percpu_hash_kmalloc(int cpu)
77+
{
78+
__u64 start_time;
79+
int i;
80+
81+
start_time = time_get_ns();
82+
for (i = 0; i < MAX_CNT; i++)
83+
syscall(__NR_getegid);
84+
printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n",
85+
cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
86+
}
87+
88+
static void loop(int cpu)
89+
{
90+
cpu_set_t cpuset;
91+
92+
CPU_ZERO(&cpuset);
93+
CPU_SET(cpu, &cpuset);
94+
sched_setaffinity(0, sizeof(cpuset), &cpuset);
95+
96+
if (test_flags & HASH_PREALLOC)
97+
test_hash_prealloc(cpu);
98+
99+
if (test_flags & PERCPU_HASH_PREALLOC)
100+
test_percpu_hash_prealloc(cpu);
101+
102+
if (test_flags & HASH_KMALLOC)
103+
test_hash_kmalloc(cpu);
104+
105+
if (test_flags & PERCPU_HASH_KMALLOC)
106+
test_percpu_hash_kmalloc(cpu);
107+
}
108+
109+
static void run_perf_test(int tasks)
110+
{
111+
pid_t pid[tasks];
112+
int i;
113+
114+
for (i = 0; i < tasks; i++) {
115+
pid[i] = fork();
116+
if (pid[i] == 0) {
117+
loop(i);
118+
exit(0);
119+
} else if (pid[i] == -1) {
120+
printf("couldn't spawn #%d process\n", i);
121+
exit(1);
122+
}
123+
}
124+
for (i = 0; i < tasks; i++) {
125+
int status;
126+
127+
assert(waitpid(pid[i], &status, 0) == pid[i]);
128+
assert(status == 0);
129+
}
130+
}
131+
132+
int main(int argc, char **argv)
133+
{
134+
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
135+
char filename[256];
136+
int num_cpu = 8;
137+
138+
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
139+
setrlimit(RLIMIT_MEMLOCK, &r);
140+
141+
if (argc > 1)
142+
test_flags = atoi(argv[1]) ? : test_flags;
143+
144+
if (argc > 2)
145+
num_cpu = atoi(argv[2]) ? : num_cpu;
146+
147+
if (load_bpf_file(filename)) {
148+
printf("%s", bpf_log_buf);
149+
return 1;
150+
}
151+
152+
run_perf_test(num_cpu);
153+
154+
return 0;
155+
}

0 commit comments

Comments
 (0)