aboutsummaryrefslogtreecommitdiffstats
path: root/samples/bpf
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@fb.com>2016-03-08 18:07:54 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-08 23:22:03 -0500
commit26e9093110fb9ceb10093e4914b129b58d49a425 (patch)
treee0bb3b8bf19cda7bfcbe3426ad45d5e075494da7 /samples/bpf
parent7dcc42b685b4acf7b2f3f08d157f1574e1bec7f7 (diff)
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 <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples/bpf')
-rw-r--r--samples/bpf/Makefile4
-rw-r--r--samples/bpf/map_perf_test_kern.c100
-rw-r--r--samples/bpf/map_perf_test_user.c155
3 files changed, 259 insertions, 0 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 75a13e742ab4..502c9fc8db85 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -18,6 +18,7 @@ hostprogs-y += trace_output
18hostprogs-y += lathist 18hostprogs-y += lathist
19hostprogs-y += offwaketime 19hostprogs-y += offwaketime
20hostprogs-y += spintest 20hostprogs-y += spintest
21hostprogs-y += map_perf_test
21 22
22test_verifier-objs := test_verifier.o libbpf.o 23test_verifier-objs := test_verifier.o libbpf.o
23test_maps-objs := test_maps.o libbpf.o 24test_maps-objs := test_maps.o libbpf.o
@@ -36,6 +37,7 @@ trace_output-objs := bpf_load.o libbpf.o trace_output_user.o
36lathist-objs := bpf_load.o libbpf.o lathist_user.o 37lathist-objs := bpf_load.o libbpf.o lathist_user.o
37offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o 38offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o
38spintest-objs := bpf_load.o libbpf.o spintest_user.o 39spintest-objs := bpf_load.o libbpf.o spintest_user.o
40map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
39 41
40# Tell kbuild to always build the programs 42# Tell kbuild to always build the programs
41always := $(hostprogs-y) 43always := $(hostprogs-y)
@@ -53,6 +55,7 @@ always += tcbpf1_kern.o
53always += lathist_kern.o 55always += lathist_kern.o
54always += offwaketime_kern.o 56always += offwaketime_kern.o
55always += spintest_kern.o 57always += spintest_kern.o
58always += map_perf_test_kern.o
56 59
57HOSTCFLAGS += -I$(objtree)/usr/include 60HOSTCFLAGS += -I$(objtree)/usr/include
58 61
@@ -71,6 +74,7 @@ HOSTLOADLIBES_trace_output += -lelf -lrt
71HOSTLOADLIBES_lathist += -lelf 74HOSTLOADLIBES_lathist += -lelf
72HOSTLOADLIBES_offwaketime += -lelf 75HOSTLOADLIBES_offwaketime += -lelf
73HOSTLOADLIBES_spintest += -lelf 76HOSTLOADLIBES_spintest += -lelf
77HOSTLOADLIBES_map_perf_test += -lelf -lrt
74 78
75# point this to your LLVM backend with bpf support 79# point this to your LLVM backend with bpf support
76LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc 80LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c
new file mode 100644
index 000000000000..311538e5a701
--- /dev/null
+++ b/samples/bpf/map_perf_test_kern.c
@@ -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
15struct 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
22struct 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
29struct 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
37struct 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
45SEC("kprobe/sys_getuid")
46int 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
59SEC("kprobe/sys_geteuid")
60int 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}
72SEC("kprobe/sys_getgid")
73int 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
86SEC("kprobe/sys_getegid")
87int 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}
99char _license[] SEC("license") = "GPL";
100u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/map_perf_test_user.c b/samples/bpf/map_perf_test_user.c
new file mode 100644
index 000000000000..95af56ec5739
--- /dev/null
+++ b/samples/bpf/map_perf_test_user.c
@@ -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
25static __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
38static int test_flags = ~0;
39
40static 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
52static 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
64static 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
76static 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
88static 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
109static 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
132int 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}