.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * benchmark.c: |
---|
3 | 4 | * Author: Konstantin Khlebnikov <koct9i@gmail.com> |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | 5 | */ |
---|
14 | 6 | #include <linux/radix-tree.h> |
---|
15 | 7 | #include <linux/slab.h> |
---|
16 | 8 | #include <linux/errno.h> |
---|
17 | 9 | #include <time.h> |
---|
18 | 10 | #include "test.h" |
---|
19 | | - |
---|
20 | | -#define for_each_index(i, base, order) \ |
---|
21 | | - for (i = base; i < base + (1 << order); i++) |
---|
22 | 11 | |
---|
23 | 12 | #define NSEC_PER_SEC 1000000000L |
---|
24 | 13 | |
---|
.. | .. |
---|
61 | 50 | } |
---|
62 | 51 | |
---|
63 | 52 | static void benchmark_insert(struct radix_tree_root *root, |
---|
64 | | - unsigned long size, unsigned long step, int order) |
---|
| 53 | + unsigned long size, unsigned long step) |
---|
65 | 54 | { |
---|
66 | 55 | struct timespec start, finish; |
---|
67 | 56 | unsigned long index; |
---|
.. | .. |
---|
70 | 59 | clock_gettime(CLOCK_MONOTONIC, &start); |
---|
71 | 60 | |
---|
72 | 61 | for (index = 0 ; index < size ; index += step) |
---|
73 | | - item_insert_order(root, index, order); |
---|
| 62 | + item_insert(root, index); |
---|
74 | 63 | |
---|
75 | 64 | clock_gettime(CLOCK_MONOTONIC, &finish); |
---|
76 | 65 | |
---|
77 | 66 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + |
---|
78 | 67 | (finish.tv_nsec - start.tv_nsec); |
---|
79 | 68 | |
---|
80 | | - printv(2, "Size: %8ld, step: %8ld, order: %d, insertion: %15lld ns\n", |
---|
81 | | - size, step, order, nsec); |
---|
| 69 | + printv(2, "Size: %8ld, step: %8ld, insertion: %15lld ns\n", |
---|
| 70 | + size, step, nsec); |
---|
82 | 71 | } |
---|
83 | 72 | |
---|
84 | 73 | static void benchmark_tagging(struct radix_tree_root *root, |
---|
85 | | - unsigned long size, unsigned long step, int order) |
---|
| 74 | + unsigned long size, unsigned long step) |
---|
86 | 75 | { |
---|
87 | 76 | struct timespec start, finish; |
---|
88 | 77 | unsigned long index; |
---|
.. | .. |
---|
98 | 87 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + |
---|
99 | 88 | (finish.tv_nsec - start.tv_nsec); |
---|
100 | 89 | |
---|
101 | | - printv(2, "Size: %8ld, step: %8ld, order: %d, tagging: %17lld ns\n", |
---|
102 | | - size, step, order, nsec); |
---|
| 90 | + printv(2, "Size: %8ld, step: %8ld, tagging: %17lld ns\n", |
---|
| 91 | + size, step, nsec); |
---|
103 | 92 | } |
---|
104 | 93 | |
---|
105 | 94 | static void benchmark_delete(struct radix_tree_root *root, |
---|
106 | | - unsigned long size, unsigned long step, int order) |
---|
| 95 | + unsigned long size, unsigned long step) |
---|
107 | 96 | { |
---|
108 | 97 | struct timespec start, finish; |
---|
109 | | - unsigned long index, i; |
---|
| 98 | + unsigned long index; |
---|
110 | 99 | long long nsec; |
---|
111 | 100 | |
---|
112 | 101 | clock_gettime(CLOCK_MONOTONIC, &start); |
---|
113 | 102 | |
---|
114 | 103 | for (index = 0 ; index < size ; index += step) |
---|
115 | | - for_each_index(i, index, order) |
---|
116 | | - item_delete(root, i); |
---|
| 104 | + item_delete(root, index); |
---|
117 | 105 | |
---|
118 | 106 | clock_gettime(CLOCK_MONOTONIC, &finish); |
---|
119 | 107 | |
---|
120 | 108 | nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + |
---|
121 | 109 | (finish.tv_nsec - start.tv_nsec); |
---|
122 | 110 | |
---|
123 | | - printv(2, "Size: %8ld, step: %8ld, order: %d, deletion: %16lld ns\n", |
---|
124 | | - size, step, order, nsec); |
---|
| 111 | + printv(2, "Size: %8ld, step: %8ld, deletion: %16lld ns\n", |
---|
| 112 | + size, step, nsec); |
---|
125 | 113 | } |
---|
126 | 114 | |
---|
127 | | -static void benchmark_size(unsigned long size, unsigned long step, int order) |
---|
| 115 | +static void benchmark_size(unsigned long size, unsigned long step) |
---|
128 | 116 | { |
---|
129 | 117 | RADIX_TREE(tree, GFP_KERNEL); |
---|
130 | 118 | long long normal, tagged; |
---|
131 | 119 | |
---|
132 | | - benchmark_insert(&tree, size, step, order); |
---|
133 | | - benchmark_tagging(&tree, size, step, order); |
---|
| 120 | + benchmark_insert(&tree, size, step); |
---|
| 121 | + benchmark_tagging(&tree, size, step); |
---|
134 | 122 | |
---|
135 | 123 | tagged = benchmark_iter(&tree, true); |
---|
136 | 124 | normal = benchmark_iter(&tree, false); |
---|
137 | 125 | |
---|
138 | | - printv(2, "Size: %8ld, step: %8ld, order: %d, tagged iteration: %8lld ns\n", |
---|
139 | | - size, step, order, tagged); |
---|
140 | | - printv(2, "Size: %8ld, step: %8ld, order: %d, normal iteration: %8lld ns\n", |
---|
141 | | - size, step, order, normal); |
---|
| 126 | + printv(2, "Size: %8ld, step: %8ld, tagged iteration: %8lld ns\n", |
---|
| 127 | + size, step, tagged); |
---|
| 128 | + printv(2, "Size: %8ld, step: %8ld, normal iteration: %8lld ns\n", |
---|
| 129 | + size, step, normal); |
---|
142 | 130 | |
---|
143 | | - benchmark_delete(&tree, size, step, order); |
---|
| 131 | + benchmark_delete(&tree, size, step); |
---|
144 | 132 | |
---|
145 | 133 | item_kill_tree(&tree); |
---|
146 | 134 | rcu_barrier(); |
---|
147 | | -} |
---|
148 | | - |
---|
149 | | -static long long __benchmark_split(unsigned long index, |
---|
150 | | - int old_order, int new_order) |
---|
151 | | -{ |
---|
152 | | - struct timespec start, finish; |
---|
153 | | - long long nsec; |
---|
154 | | - RADIX_TREE(tree, GFP_ATOMIC); |
---|
155 | | - |
---|
156 | | - item_insert_order(&tree, index, old_order); |
---|
157 | | - |
---|
158 | | - clock_gettime(CLOCK_MONOTONIC, &start); |
---|
159 | | - radix_tree_split(&tree, index, new_order); |
---|
160 | | - clock_gettime(CLOCK_MONOTONIC, &finish); |
---|
161 | | - nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + |
---|
162 | | - (finish.tv_nsec - start.tv_nsec); |
---|
163 | | - |
---|
164 | | - item_kill_tree(&tree); |
---|
165 | | - |
---|
166 | | - return nsec; |
---|
167 | | - |
---|
168 | | -} |
---|
169 | | - |
---|
170 | | -static void benchmark_split(unsigned long size, unsigned long step) |
---|
171 | | -{ |
---|
172 | | - int i, j, idx; |
---|
173 | | - long long nsec = 0; |
---|
174 | | - |
---|
175 | | - |
---|
176 | | - for (idx = 0; idx < size; idx += step) { |
---|
177 | | - for (i = 3; i < 11; i++) { |
---|
178 | | - for (j = 0; j < i; j++) { |
---|
179 | | - nsec += __benchmark_split(idx, i, j); |
---|
180 | | - } |
---|
181 | | - } |
---|
182 | | - } |
---|
183 | | - |
---|
184 | | - printv(2, "Size %8ld, step %8ld, split time %10lld ns\n", |
---|
185 | | - size, step, nsec); |
---|
186 | | - |
---|
187 | | -} |
---|
188 | | - |
---|
189 | | -static long long __benchmark_join(unsigned long index, |
---|
190 | | - unsigned order1, unsigned order2) |
---|
191 | | -{ |
---|
192 | | - unsigned long loc; |
---|
193 | | - struct timespec start, finish; |
---|
194 | | - long long nsec; |
---|
195 | | - void *item, *item2 = item_create(index + 1, order1); |
---|
196 | | - RADIX_TREE(tree, GFP_KERNEL); |
---|
197 | | - |
---|
198 | | - item_insert_order(&tree, index, order2); |
---|
199 | | - item = radix_tree_lookup(&tree, index); |
---|
200 | | - |
---|
201 | | - clock_gettime(CLOCK_MONOTONIC, &start); |
---|
202 | | - radix_tree_join(&tree, index + 1, order1, item2); |
---|
203 | | - clock_gettime(CLOCK_MONOTONIC, &finish); |
---|
204 | | - nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC + |
---|
205 | | - (finish.tv_nsec - start.tv_nsec); |
---|
206 | | - |
---|
207 | | - loc = find_item(&tree, item); |
---|
208 | | - if (loc == -1) |
---|
209 | | - free(item); |
---|
210 | | - |
---|
211 | | - item_kill_tree(&tree); |
---|
212 | | - |
---|
213 | | - return nsec; |
---|
214 | | -} |
---|
215 | | - |
---|
216 | | -static void benchmark_join(unsigned long step) |
---|
217 | | -{ |
---|
218 | | - int i, j, idx; |
---|
219 | | - long long nsec = 0; |
---|
220 | | - |
---|
221 | | - for (idx = 0; idx < 1 << 10; idx += step) { |
---|
222 | | - for (i = 1; i < 15; i++) { |
---|
223 | | - for (j = 0; j < i; j++) { |
---|
224 | | - nsec += __benchmark_join(idx, i, j); |
---|
225 | | - } |
---|
226 | | - } |
---|
227 | | - } |
---|
228 | | - |
---|
229 | | - printv(2, "Size %8d, step %8ld, join time %10lld ns\n", |
---|
230 | | - 1 << 10, step, nsec); |
---|
231 | 135 | } |
---|
232 | 136 | |
---|
233 | 137 | void benchmark(void) |
---|
.. | .. |
---|
242 | 146 | |
---|
243 | 147 | for (c = 0; size[c]; c++) |
---|
244 | 148 | for (s = 0; step[s]; s++) |
---|
245 | | - benchmark_size(size[c], step[s], 0); |
---|
246 | | - |
---|
247 | | - for (c = 0; size[c]; c++) |
---|
248 | | - for (s = 0; step[s]; s++) |
---|
249 | | - benchmark_size(size[c], step[s] << 9, 9); |
---|
250 | | - |
---|
251 | | - for (c = 0; size[c]; c++) |
---|
252 | | - for (s = 0; step[s]; s++) |
---|
253 | | - benchmark_split(size[c], step[s]); |
---|
254 | | - |
---|
255 | | - for (s = 0; step[s]; s++) |
---|
256 | | - benchmark_join(step[s]); |
---|
| 149 | + benchmark_size(size[c], step[s]); |
---|
257 | 150 | } |
---|