Commit | Line | Data |
---|---|---|
fec0f21c JA |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | ||
5 | #include "../fio.h" | |
6 | #include "../gettime.h" | |
7 | #include "../time.h" | |
8 | #include "../verify.h" | |
9 | ||
10 | #include "../crc/md5.h" | |
11 | #include "../crc/crc64.h" | |
12 | #include "../crc/crc32.h" | |
13 | #include "../crc/crc32c.h" | |
14 | #include "../crc/crc16.h" | |
15 | #include "../crc/crc7.h" | |
16 | #include "../crc/sha1.h" | |
17 | #include "../crc/sha256.h" | |
18 | #include "../crc/sha512.h" | |
844ea602 | 19 | #include "../crc/xxhash.h" |
fec0f21c | 20 | |
f7540869 JA |
21 | #define CHUNK 131072U |
22 | #define NR_CHUNKS 2048U | |
fec0f21c JA |
23 | |
24 | struct test_type { | |
25 | const char *name; | |
26 | unsigned int mask; | |
27 | uint64_t (*fn)(void); | |
28 | }; | |
29 | ||
30 | enum { | |
31 | T_MD5 = 1U << 0, | |
32 | T_CRC64 = 1U << 1, | |
33 | T_CRC32 = 1U << 2, | |
34 | T_CRC32C = 1U << 3, | |
35 | T_CRC16 = 1U << 4, | |
36 | T_CRC7 = 1U << 5, | |
37 | T_SHA1 = 1U << 6, | |
38 | T_SHA256 = 1U << 7, | |
39 | T_SHA512 = 1U << 8, | |
844ea602 | 40 | T_XXHASH = 1U << 9, |
fec0f21c JA |
41 | }; |
42 | ||
43 | static void randomize_buf(void *buf, unsigned int size, int seed) | |
44 | { | |
45 | struct frand_state state; | |
46 | ||
47 | init_rand_seed(&state, seed); | |
48 | fill_random_buf(&state, buf, size); | |
49 | } | |
50 | ||
51 | static uint64_t t_md5(void) | |
52 | { | |
53 | uint32_t digest[4]; | |
54 | struct fio_md5_ctx ctx = { .hash = digest }; | |
55 | struct timeval s; | |
56 | uint64_t ret; | |
57 | void *buf; | |
58 | int i; | |
59 | ||
60 | fio_md5_init(&ctx); | |
61 | ||
62 | buf = malloc(CHUNK); | |
63 | randomize_buf(buf, CHUNK, 0x8989); | |
64 | ||
65 | fio_gettime(&s, NULL); | |
66 | for (i = 0; i < NR_CHUNKS; i++) | |
67 | fio_md5_update(&ctx, buf, CHUNK); | |
68 | ||
69 | ret = utime_since_now(&s); | |
70 | free(buf); | |
71 | return ret; | |
72 | } | |
73 | ||
74 | static uint64_t t_crc64(void) | |
75 | { | |
76 | struct timeval s; | |
77 | uint64_t ret; | |
78 | void *buf; | |
79 | int i; | |
80 | ||
81 | buf = malloc(CHUNK); | |
82 | randomize_buf(buf, CHUNK, 0x8989); | |
83 | ||
84 | fio_gettime(&s, NULL); | |
85 | for (i = 0; i < NR_CHUNKS; i++) | |
86 | fio_crc64(buf, CHUNK); | |
87 | ||
88 | ret = utime_since_now(&s); | |
89 | free(buf); | |
90 | return ret; | |
91 | } | |
92 | ||
93 | static uint64_t t_crc32(void) | |
94 | { | |
95 | struct timeval s; | |
96 | uint64_t ret; | |
97 | void *buf; | |
98 | int i; | |
99 | ||
100 | buf = malloc(CHUNK); | |
101 | randomize_buf(buf, CHUNK, 0x8989); | |
102 | ||
103 | fio_gettime(&s, NULL); | |
104 | for (i = 0; i < NR_CHUNKS; i++) | |
105 | fio_crc32(buf, CHUNK); | |
106 | ||
107 | ret = utime_since_now(&s); | |
108 | free(buf); | |
109 | return ret; | |
110 | } | |
111 | ||
112 | static uint64_t t_crc32c(void) | |
113 | { | |
114 | struct timeval s; | |
115 | uint64_t ret; | |
116 | void *buf; | |
117 | int i; | |
118 | ||
119 | buf = malloc(CHUNK); | |
120 | randomize_buf(buf, CHUNK, 0x8989); | |
121 | ||
122 | fio_gettime(&s, NULL); | |
123 | for (i = 0; i < NR_CHUNKS; i++) | |
124 | fio_crc32c(buf, CHUNK); | |
125 | ||
126 | ret = utime_since_now(&s); | |
127 | free(buf); | |
128 | return ret; | |
129 | } | |
130 | ||
131 | static uint64_t t_crc16(void) | |
132 | { | |
133 | struct timeval s; | |
134 | uint64_t ret; | |
135 | void *buf; | |
136 | int i; | |
137 | ||
138 | buf = malloc(CHUNK); | |
139 | randomize_buf(buf, CHUNK, 0x8989); | |
140 | ||
141 | fio_gettime(&s, NULL); | |
142 | for (i = 0; i < NR_CHUNKS; i++) | |
143 | fio_crc16(buf, CHUNK); | |
144 | ||
145 | ret = utime_since_now(&s); | |
146 | free(buf); | |
147 | return ret; | |
148 | } | |
149 | ||
150 | static uint64_t t_crc7(void) | |
151 | { | |
152 | struct timeval s; | |
153 | uint64_t ret; | |
154 | void *buf; | |
155 | int i; | |
156 | ||
157 | buf = malloc(CHUNK); | |
158 | randomize_buf(buf, CHUNK, 0x8989); | |
159 | ||
160 | fio_gettime(&s, NULL); | |
161 | for (i = 0; i < NR_CHUNKS; i++) | |
162 | fio_crc7(buf, CHUNK); | |
163 | ||
164 | ret = utime_since_now(&s); | |
165 | free(buf); | |
166 | return ret; | |
167 | } | |
168 | ||
169 | static uint64_t t_sha1(void) | |
170 | { | |
171 | uint32_t sha[5]; | |
172 | struct fio_sha1_ctx ctx = { .H = sha }; | |
173 | struct timeval s; | |
174 | uint64_t ret; | |
175 | void *buf; | |
176 | int i; | |
177 | ||
178 | fio_sha1_init(&ctx); | |
179 | ||
180 | buf = malloc(CHUNK); | |
181 | randomize_buf(buf, CHUNK, 0x8989); | |
182 | ||
183 | fio_gettime(&s, NULL); | |
184 | for (i = 0; i < NR_CHUNKS; i++) | |
185 | fio_sha1_update(&ctx, buf, CHUNK); | |
186 | ||
187 | ret = utime_since_now(&s); | |
188 | free(buf); | |
189 | return ret; | |
190 | } | |
191 | ||
192 | static uint64_t t_sha256(void) | |
193 | { | |
194 | uint8_t sha[64]; | |
195 | struct fio_sha256_ctx ctx = { .buf = sha }; | |
196 | struct timeval s; | |
197 | uint64_t ret; | |
198 | void *buf; | |
199 | int i; | |
200 | ||
201 | fio_sha256_init(&ctx); | |
202 | ||
203 | buf = malloc(CHUNK); | |
204 | randomize_buf(buf, CHUNK, 0x8989); | |
205 | ||
206 | fio_gettime(&s, NULL); | |
207 | for (i = 0; i < NR_CHUNKS; i++) | |
208 | fio_sha256_update(&ctx, buf, CHUNK); | |
209 | ||
210 | ret = utime_since_now(&s); | |
211 | free(buf); | |
212 | return ret; | |
213 | } | |
214 | ||
215 | static uint64_t t_sha512(void) | |
216 | { | |
217 | uint8_t sha[128]; | |
218 | struct fio_sha512_ctx ctx = { .buf = sha }; | |
219 | struct timeval s; | |
220 | uint64_t ret; | |
221 | void *buf; | |
222 | int i; | |
223 | ||
224 | fio_sha512_init(&ctx); | |
225 | ||
226 | buf = malloc(CHUNK); | |
227 | randomize_buf(buf, CHUNK, 0x8989); | |
228 | ||
229 | fio_gettime(&s, NULL); | |
230 | for (i = 0; i < NR_CHUNKS; i++) | |
231 | fio_sha512_update(&ctx, buf, CHUNK); | |
232 | ||
233 | ret = utime_since_now(&s); | |
234 | free(buf); | |
235 | return ret; | |
236 | } | |
237 | ||
844ea602 JA |
238 | static uint64_t t_xxhash(void) |
239 | { | |
240 | void *state; | |
241 | struct timeval s; | |
242 | uint64_t ret; | |
243 | void *buf; | |
244 | int i; | |
245 | ||
246 | state = XXH32_init(0x8989); | |
247 | ||
248 | buf = malloc(CHUNK); | |
249 | randomize_buf(buf, CHUNK, 0x8989); | |
250 | ||
251 | fio_gettime(&s, NULL); | |
252 | for (i = 0; i < NR_CHUNKS; i++) | |
253 | XXH32_update(state, buf, CHUNK); | |
254 | ||
255 | XXH32_digest(state); | |
256 | ret = utime_since_now(&s); | |
257 | free(buf); | |
258 | return ret; | |
259 | } | |
260 | ||
fec0f21c JA |
261 | static struct test_type t[] = { |
262 | { | |
263 | .name = "md5", | |
264 | .mask = T_MD5, | |
265 | .fn = t_md5, | |
266 | }, | |
267 | { | |
268 | .name = "crc64", | |
269 | .mask = T_CRC64, | |
270 | .fn = t_crc64, | |
271 | }, | |
272 | { | |
273 | .name = "crc32", | |
274 | .mask = T_CRC32, | |
275 | .fn = t_crc32, | |
276 | }, | |
277 | { | |
278 | .name = "crc32c", | |
279 | .mask = T_CRC32C, | |
280 | .fn = t_crc32c, | |
281 | }, | |
282 | { | |
283 | .name = "crc16", | |
284 | .mask = T_CRC16, | |
285 | .fn = t_crc16, | |
286 | }, | |
287 | { | |
288 | .name = "crc7", | |
289 | .mask = T_CRC7, | |
290 | .fn = t_crc7, | |
291 | }, | |
292 | { | |
293 | .name = "sha1", | |
294 | .mask = T_SHA1, | |
295 | .fn = t_sha1, | |
296 | }, | |
297 | { | |
298 | .name = "sha256", | |
299 | .mask = T_SHA256, | |
300 | .fn = t_sha256, | |
301 | }, | |
302 | { | |
303 | .name = "sha512", | |
304 | .mask = T_SHA512, | |
305 | .fn = t_sha512, | |
306 | }, | |
844ea602 JA |
307 | { |
308 | .name = "xxhash", | |
309 | .mask = T_XXHASH, | |
310 | .fn = t_xxhash, | |
311 | }, | |
fec0f21c JA |
312 | { |
313 | .name = NULL, | |
314 | }, | |
315 | }; | |
316 | ||
317 | static unsigned int get_test_mask(const char *type) | |
318 | { | |
319 | char *ostr, *str = strdup(type); | |
320 | unsigned int mask; | |
321 | char *name; | |
322 | int i; | |
323 | ||
324 | ostr = str; | |
325 | mask = 0; | |
326 | while ((name = strsep(&str, ",")) != NULL) { | |
327 | for (i = 0; t[i].name; i++) { | |
f7540869 | 328 | if (!strcmp(t[i].name, name)) { |
fec0f21c JA |
329 | mask |= t[i].mask; |
330 | break; | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
335 | free(ostr); | |
336 | return mask; | |
337 | } | |
338 | ||
782744ef JA |
339 | static int list_types(void) |
340 | { | |
341 | int i; | |
342 | ||
343 | for (i = 0; t[i].name; i++) | |
344 | printf("%s\n", t[i].name); | |
345 | ||
346 | return 0; | |
347 | } | |
348 | ||
fec0f21c JA |
349 | int fio_crctest(const char *type) |
350 | { | |
351 | unsigned int test_mask = 0; | |
352 | uint64_t mb = CHUNK * NR_CHUNKS; | |
353 | int i; | |
354 | ||
355 | crc32c_intel_probe(); | |
356 | ||
357 | if (!type) | |
358 | test_mask = ~0U; | |
782744ef JA |
359 | else if (!strcmp(type, "help") || !strcmp(type, "list")) |
360 | return list_types(); | |
fec0f21c JA |
361 | else |
362 | test_mask = get_test_mask(type); | |
363 | ||
364 | for (i = 0; t[i].name; i++) { | |
365 | double mb_sec; | |
366 | uint64_t usec; | |
367 | ||
368 | if (!(t[i].mask & test_mask)) | |
369 | continue; | |
370 | ||
371 | usec = t[i].fn(); | |
372 | mb_sec = (double) mb / (double) usec; | |
373 | mb_sec /= (1.024 * 1.024); | |
374 | printf("%s:\t%.2f MB/sec\n", t[i].name, mb_sec); | |
375 | } | |
782744ef | 376 | |
fec0f21c JA |
377 | return 0; |
378 | } |