1 /**********************************************************************
2 Copyright(c) 2011-2018 Intel Corporation All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29
30 #define _FILE_OFFSET_BITS 64
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <getopt.h>
35 #include "huff_codes.h"
36 #include "igzip_lib.h"
37 #include "test.h"
38
39 #include <zlib.h>
40
41 #define BUF_SIZE 1024
42
43 #define OPTARGS "hl:f:z:i:d:stub:y:w:o:D:"
44
45 #define COMPRESSION_QUEUE_LIMIT 32
46 #define UNSET -1
47
48 #define xstr(a) str(a)
49 #define str(a) #a
50
51 /* Limit output buffer size to 2 Gigabytes. Since stream->avail_out is a
52 * uint32_t and there is no logic for handling an overflowed output buffer in
53 * the perf test, this define must be less then 4 Gigabytes */
54 #define MAX_COMPRESS_BUF_SIZE (1U << 31)
55
56 int level_size_buf[10] = {
57 #ifdef ISAL_DEF_LVL0_DEFAULT
58 ISAL_DEF_LVL0_DEFAULT,
59 #else
60 0,
61 #endif
62 #ifdef ISAL_DEF_LVL1_DEFAULT
63 ISAL_DEF_LVL1_DEFAULT,
64 #else
65 0,
66 #endif
67 #ifdef ISAL_DEF_LVL2_DEFAULT
68 ISAL_DEF_LVL2_DEFAULT,
69 #else
70 0,
71 #endif
72 #ifdef ISAL_DEF_LVL3_DEFAULT
73 ISAL_DEF_LVL3_DEFAULT,
74 #else
75 0,
76 #endif
77 #ifdef ISAL_DEF_LVL4_DEFAULT
78 ISAL_DEF_LVL4_DEFAULT,
79 #else
80 0,
81 #endif
82 #ifdef ISAL_DEF_LVL5_DEFAULT
83 ISAL_DEF_LVL5_DEFAULT,
84 #else
85 0,
86 #endif
87 #ifdef ISAL_DEF_LVL6_DEFAULT
88 ISAL_DEF_LVL6_DEFAULT,
89 #else
90 0,
91 #endif
92 #ifdef ISAL_DEF_LVL7_DEFAULT
93 ISAL_DEF_LVL7_DEFAULT,
94 #else
95 0,
96 #endif
97 #ifdef ISAL_DEF_LVL8_DEFAULT
98 ISAL_DEF_LVL8_DEFAULT,
99 #else
100 0,
101 #endif
102 #ifdef ISAL_DEF_LVL9_DEFAULT
103 ISAL_DEF_LVL9_DEFAULT,
104 #else
105 0,
106 #endif
107 };
108
109 enum { ISAL_STATELESS, ISAL_STATEFUL, ISAL_WITH_DICTIONARY, ZLIB };
110
111 struct compress_strategy {
112 int32_t mode;
113 int32_t level;
114 };
115
116 struct inflate_modes {
117 int32_t stateless;
118 int32_t stateful;
119 int32_t zlib;
120 };
121
122 struct perf_info {
123 char *file_name;
124 size_t file_size;
125 size_t deflate_size;
126 uint32_t inblock_size;
127 uint32_t flush_type;
128 int32_t hist_bits;
129 int32_t deflate_time;
130 int32_t inflate_time;
131 struct compress_strategy strategy;
132 uint32_t inflate_mode;
133 struct perf start;
134 };
135
136 void
init_perf_info(struct perf_info * info)137 init_perf_info(struct perf_info *info)
138 {
139 memset(info, 0, sizeof(*info));
140 info->deflate_time = BENCHMARK_TIME;
141 info->inflate_time = BENCHMARK_TIME;
142 }
143
144 int
usage(void)145 usage(void)
146 {
147 fprintf(stderr,
148 "Usage: igzip_perf [options] <infile>\n"
149 " -h help, print this message\n"
150 " The options -l, -f, -z may be used up to " xstr(
151 COMPRESSION_QUEUE_LIMIT) " times\n"
152 " -l <level> isa-l stateless deflate level to "
153 "test (" xstr(ISAL_DEF_MIN_LEVEL) "-" xstr(
154 ISAL_DEF_MAX_LEVEL) ")\n"
155 " -f <level> isa-l "
156 "stateful deflate "
157 "level to test (" xstr(ISAL_DEF_MIN_LEVEL) "-" xstr(
158 ISAL_DEF_MAX_LEVEL) ")\n"
159 " -z <level> zlib deflate level to test\n"
160 " -d <time> approx time in seconds for deflate (at least 0)\n"
161 " -i <time> approx time in seconds for inflate (at least 0)\n"
162 " -s performance test isa-l stateful inflate\n"
163 " -t performance test isa-l stateless inflate\n"
164 " -u performance test zlib inflate\n"
165 " -D <file> use dictionary file\n"
166 " -o <file> output file to store compressed data (last one if multiple)\n"
167 " -b <size> input buffer size, applies to stateful options (-f,-z,-s)\n"
168 " -y <type> flush type: 0 (default: no flush), 1 (sync flush), 2 (full flush)\n"
169 " -w <size> log base 2 size of history window, between 9 and 15\n");
170 exit(0);
171 }
172
173 void
print_perf_info_line(struct perf_info * info)174 print_perf_info_line(struct perf_info *info)
175 {
176 printf("igzip_perf-> compress level: %d flush_type: %d block_size: %d\n",
177 info->strategy.level, info->flush_type, info->inblock_size);
178 }
179
180 void
print_file_line(struct perf_info * info)181 print_file_line(struct perf_info *info)
182 {
183 printf(" file info-> name: %s file_size: %lu compress_size: %lu ratio: %2.02f%%\n",
184 info->file_name, info->file_size, info->deflate_size,
185 100.0 * info->deflate_size / info->file_size);
186 }
187
188 void
print_deflate_perf_line(struct perf_info * info)189 print_deflate_perf_line(struct perf_info *info)
190 {
191 if (info->strategy.mode == ISAL_STATELESS)
192 printf(" isal_stateless_deflate-> ");
193 else if (info->strategy.mode == ISAL_STATEFUL)
194 printf(" isal_stateful_deflate-> ");
195 else if (info->strategy.mode == ISAL_WITH_DICTIONARY)
196 printf(" isal_dictionary_deflate-> ");
197 else if (info->strategy.mode == ZLIB)
198 printf(" zlib_deflate-> ");
199
200 perf_print(info->start, info->file_size);
201 }
202
203 void
print_inflate_perf_line(struct perf_info * info)204 print_inflate_perf_line(struct perf_info *info)
205 {
206 if (info->inflate_mode == ISAL_STATELESS)
207 printf(" isal_stateless_inflate-> ");
208 else if (info->inflate_mode == ISAL_STATEFUL)
209 printf(" isal_stateful_inflate-> ");
210 else if (info->inflate_mode == ISAL_WITH_DICTIONARY)
211 printf(" isal_dictionary_inflate-> ");
212 else if (info->inflate_mode == ZLIB)
213 printf(" zlib_inflate-> ");
214
215 perf_print(info->start, info->file_size);
216 }
217
218 int
isal_deflate_round(struct isal_zstream * stream,uint8_t * outbuf,uint32_t outbuf_size,uint8_t * inbuf,uint32_t inbuf_size,uint32_t level,uint8_t * level_buf,uint32_t level_buf_size,int flush_type,int hist_bits)219 isal_deflate_round(struct isal_zstream *stream, uint8_t *outbuf, uint32_t outbuf_size,
220 uint8_t *inbuf, uint32_t inbuf_size, uint32_t level, uint8_t *level_buf,
221 uint32_t level_buf_size, int flush_type, int hist_bits)
222 {
223 int check;
224
225 /* Setup stream for stateless compression */
226 isal_deflate_init(stream);
227 stream->end_of_stream = 1; /* Do the entire file at once */
228 stream->flush = flush_type;
229 stream->next_in = inbuf;
230 stream->avail_in = inbuf_size;
231 stream->next_out = outbuf;
232 stream->avail_out = outbuf_size;
233 stream->level = level;
234 stream->level_buf = level_buf;
235 stream->level_buf_size = level_buf_size;
236 stream->hist_bits = hist_bits;
237
238 /* Compress stream */
239 check = isal_deflate_stateless(stream);
240
241 /* Verify compression success */
242 if (check || stream->avail_in)
243 return 1;
244
245 return 0;
246 }
247
248 int
isal_deflate_dict_round(struct isal_zstream * stream,uint8_t * outbuf,uint32_t outbuf_size,uint8_t * inbuf,uint32_t inbuf_size,uint32_t level,uint8_t * level_buf,uint32_t level_buf_size,int flush_type,int hist_bits,struct isal_dict * dict_str)249 isal_deflate_dict_round(struct isal_zstream *stream, uint8_t *outbuf, uint32_t outbuf_size,
250 uint8_t *inbuf, uint32_t inbuf_size, uint32_t level, uint8_t *level_buf,
251 uint32_t level_buf_size, int flush_type, int hist_bits,
252 struct isal_dict *dict_str)
253 {
254 int check;
255
256 /* Setup stream for compression with dictionary */
257 isal_deflate_init(stream);
258 stream->level = level;
259 stream->level_buf = level_buf;
260 stream->level_buf_size = level_buf_size;
261
262 if (COMP_OK != isal_deflate_reset_dict(stream, dict_str))
263 return 1;
264
265 stream->end_of_stream = 1;
266 stream->flush = flush_type;
267 stream->next_in = inbuf;
268 stream->avail_in = inbuf_size;
269 stream->next_out = outbuf;
270 stream->avail_out = outbuf_size;
271 stream->hist_bits = hist_bits;
272
273 check = isal_deflate(stream);
274
275 /* Verify Compression Success */
276 if (COMP_OK != check || stream->avail_in > 0)
277 return 1;
278
279 return 0;
280 }
281
282 int
isal_inflate_round(struct inflate_state * state,uint8_t * inbuf,uint32_t inbuf_size,uint8_t * outbuf,uint32_t outbuf_size,int hist_bits)283 isal_inflate_round(struct inflate_state *state, uint8_t *inbuf, uint32_t inbuf_size,
284 uint8_t *outbuf, uint32_t outbuf_size, int hist_bits)
285 {
286 int check = 0;
287
288 /* Setup for stateless inflate */
289 state->next_in = inbuf;
290 state->avail_in = inbuf_size;
291 state->next_out = outbuf;
292 state->avail_out = outbuf_size;
293 state->crc_flag = ISAL_DEFLATE;
294 state->hist_bits = hist_bits;
295
296 /* Inflate data */
297 check = isal_inflate_stateless(state);
298
299 /* Verify inflate was successful */
300 if (check)
301 return 1;
302
303 return 0;
304 }
305
306 int
isal_deflate_stateful_round(struct isal_zstream * stream,uint8_t * outbuf,uint32_t outbuf_size,uint8_t * inbuf,uint32_t inbuf_size,uint32_t in_block_size,uint32_t level,uint8_t * level_buf,uint32_t level_buf_size,int flush_type,int hist_bits)307 isal_deflate_stateful_round(struct isal_zstream *stream, uint8_t *outbuf, uint32_t outbuf_size,
308 uint8_t *inbuf, uint32_t inbuf_size, uint32_t in_block_size,
309 uint32_t level, uint8_t *level_buf, uint32_t level_buf_size,
310 int flush_type, int hist_bits)
311 {
312 uint64_t inbuf_remaining;
313 int check = COMP_OK;
314
315 /* Setup stream for stateful compression */
316 inbuf_remaining = inbuf_size;
317 isal_deflate_init(stream);
318 stream->flush = flush_type;
319 stream->next_in = inbuf;
320 stream->next_out = outbuf;
321 stream->avail_out = outbuf_size;
322 stream->level = level;
323 stream->level_buf = level_buf;
324 stream->level_buf_size = level_buf_size;
325 stream->hist_bits = hist_bits;
326
327 /* Keep compressing so long as more data is available and no error has
328 * been hit */
329 while (COMP_OK == check && inbuf_remaining > in_block_size) {
330 /* Setup next in buffer, assumes out buffer is sufficiently
331 * large */
332 stream->avail_in = in_block_size;
333 inbuf_remaining -= in_block_size;
334
335 /* Compress stream */
336 check = isal_deflate(stream);
337 }
338
339 /* Finish compressing all remaining input */
340 if (COMP_OK == check) {
341 stream->avail_in = inbuf_remaining;
342 stream->end_of_stream = 1;
343 check = isal_deflate(stream);
344 }
345
346 /* Verify Compression Success */
347 if (COMP_OK != check || stream->avail_in > 0)
348 return 1;
349
350 return 0;
351 }
352
353 int
isal_inflate_stateful_round(struct inflate_state * state,uint8_t * inbuf,uint32_t inbuf_size,uint32_t in_block_size,uint8_t * outbuf,uint32_t outbuf_size,int hist_bits,uint8_t * dict_buf,int dict_file_size)354 isal_inflate_stateful_round(struct inflate_state *state, uint8_t *inbuf, uint32_t inbuf_size,
355 uint32_t in_block_size, uint8_t *outbuf, uint32_t outbuf_size,
356 int hist_bits, uint8_t *dict_buf, int dict_file_size)
357 {
358 int check = ISAL_DECOMP_OK;
359 uint64_t inbuf_remaining;
360
361 isal_inflate_init(state);
362 state->next_in = inbuf;
363 state->next_out = outbuf;
364 state->avail_out = outbuf_size;
365 state->hist_bits = hist_bits;
366 if (dict_file_size != 0)
367 isal_inflate_set_dict(state, dict_buf, dict_file_size);
368
369 inbuf_remaining = inbuf_size;
370
371 while (ISAL_DECOMP_OK == check && inbuf_remaining >= in_block_size) {
372 state->avail_in = in_block_size;
373 inbuf_remaining -= in_block_size;
374 check = isal_inflate(state);
375 }
376 if (ISAL_DECOMP_OK == check && inbuf_remaining > 0) {
377 state->avail_in = inbuf_remaining;
378 check = isal_inflate(state);
379 }
380
381 if (ISAL_DECOMP_OK != check || state->avail_in > 0)
382 return 1;
383
384 return 0;
385 }
386
387 int
zlib_deflate_round(z_stream * gstream,uint8_t * outbuf,uInt outbuf_size,uint8_t * inbuf,uLong inbuf_size,uLong in_block_size,int level,int flush_type)388 zlib_deflate_round(z_stream *gstream, uint8_t *outbuf, uInt outbuf_size, uint8_t *inbuf,
389 uLong inbuf_size, uLong in_block_size, int level, int flush_type)
390 {
391 uLong inbuf_remaining;
392 int check = Z_OK;
393
394 inbuf_remaining = inbuf_size;
395
396 /* Setup stream for stateful compression */
397 if (0 != deflateReset(gstream))
398 return 1;
399
400 gstream->next_in = inbuf;
401 gstream->next_out = outbuf;
402 gstream->avail_out = outbuf_size;
403
404 /* Keep compressing so long as more data is available and no error has
405 * been hit */
406 while (Z_OK == check && inbuf_remaining > in_block_size) {
407 gstream->avail_in = in_block_size;
408 inbuf_remaining -= in_block_size;
409 check = deflate(gstream, flush_type);
410 }
411
412 /* Finish compressing all remaining input */
413 if (Z_OK == check) {
414 gstream->avail_in = inbuf_remaining;
415 check = deflate(gstream, Z_FINISH);
416 }
417
418 /* Verify Compression Success */
419 if (Z_STREAM_END != check)
420 return 1;
421
422 return 0;
423 }
424
425 int
zlib_inflate_round(z_stream * gstream,uint8_t * inbuf,uLong inbuf_size,uint8_t * outbuf,uInt outbuf_size)426 zlib_inflate_round(z_stream *gstream, uint8_t *inbuf, uLong inbuf_size, uint8_t *outbuf,
427 uInt outbuf_size)
428 {
429 int check = 0;
430
431 if (0 != inflateReset(gstream))
432 return 1;
433
434 gstream->next_in = inbuf;
435 gstream->avail_in = inbuf_size;
436 gstream->next_out = outbuf;
437 gstream->avail_out = outbuf_size;
438 check = inflate(gstream, Z_FINISH);
439 if (check != Z_STREAM_END)
440 return 1;
441
442 return 0;
443 }
444
445 int
isal_deflate_perf(uint8_t * outbuf,uint64_t * outbuf_size,uint8_t * inbuf,uint64_t inbuf_size,int level,int flush_type,int hist_bits,int time,struct perf * start)446 isal_deflate_perf(uint8_t *outbuf, uint64_t *outbuf_size, uint8_t *inbuf, uint64_t inbuf_size,
447 int level, int flush_type, int hist_bits, int time, struct perf *start)
448 {
449 struct isal_zstream stream;
450 uint8_t *level_buf = NULL;
451 int check;
452
453 if (level_size_buf[level] > 0) {
454 level_buf = malloc(level_size_buf[level]);
455 if (level_buf == NULL)
456 return 1;
457 }
458
459 BENCHMARK(start, time,
460 check = isal_deflate_round(&stream, outbuf, *outbuf_size, inbuf, inbuf_size,
461 level, level_buf, level_size_buf[level], flush_type,
462 hist_bits));
463 *outbuf_size = stream.total_out;
464 return check;
465 }
466
467 int
isal_deflate_dict_perf(uint8_t * outbuf,uint64_t * outbuf_size,uint8_t * inbuf,uint64_t inbuf_size,int level,int flush_type,int hist_bits,int time,struct perf * start,uint8_t * dict_buf,int dict_file_size)468 isal_deflate_dict_perf(uint8_t *outbuf, uint64_t *outbuf_size, uint8_t *inbuf, uint64_t inbuf_size,
469 int level, int flush_type, int hist_bits, int time, struct perf *start,
470 uint8_t *dict_buf, int dict_file_size)
471 {
472 struct isal_zstream stream;
473 struct isal_dict dict_str;
474 uint8_t *level_buf = NULL;
475 int check;
476
477 if (level_size_buf[level] > 0) {
478 level_buf = malloc(level_size_buf[level]);
479 if (level_buf == NULL)
480 return 1;
481 }
482
483 stream.level = level;
484 if (isal_deflate_process_dict(&stream, &dict_str, dict_buf, dict_file_size) != COMP_OK) {
485 if (level_buf != NULL)
486 free(level_buf);
487 return 1;
488 }
489
490 BENCHMARK(start, time,
491 check = isal_deflate_dict_round(&stream, outbuf, *outbuf_size, inbuf, inbuf_size,
492 level, level_buf, level_size_buf[level],
493 flush_type, hist_bits, &dict_str));
494 if (level_buf != NULL)
495 free(level_buf);
496 *outbuf_size = stream.total_out;
497 return check;
498 }
499
500 int
isal_deflate_stateful_perf(uint8_t * outbuf,uint64_t * outbuf_size,uint8_t * inbuf,uint64_t inbuf_size,int level,int flush_type,uint64_t in_block_size,int hist_bits,int time,struct perf * start)501 isal_deflate_stateful_perf(uint8_t *outbuf, uint64_t *outbuf_size, uint8_t *inbuf,
502 uint64_t inbuf_size, int level, int flush_type, uint64_t in_block_size,
503 int hist_bits, int time, struct perf *start)
504 {
505 struct isal_zstream stream;
506 uint8_t *level_buf = NULL;
507 int check;
508
509 if (in_block_size == 0)
510 in_block_size = inbuf_size;
511
512 if (level_size_buf[level] > 0) {
513 level_buf = malloc(level_size_buf[level]);
514 if (level_buf == NULL)
515 return 1;
516 }
517
518 BENCHMARK(start, time,
519 check = isal_deflate_stateful_round(
520 &stream, outbuf, *outbuf_size, inbuf, inbuf_size, in_block_size, level,
521 level_buf, level_size_buf[level], flush_type, hist_bits));
522 *outbuf_size = stream.total_out;
523 return check;
524 }
525
526 int
zlib_deflate_perf(uint8_t * outbuf,uint64_t * outbuf_size,uint8_t * inbuf,uint64_t inbuf_size,int level,int flush_type,uint64_t in_block_size,int hist_bits,int time,struct perf * start)527 zlib_deflate_perf(uint8_t *outbuf, uint64_t *outbuf_size, uint8_t *inbuf, uint64_t inbuf_size,
528 int level, int flush_type, uint64_t in_block_size, int hist_bits, int time,
529 struct perf *start)
530 {
531 int check;
532 z_stream gstream;
533 int flush_translator[] = { Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH };
534
535 if (in_block_size == 0)
536 in_block_size = inbuf_size;
537
538 flush_type = flush_translator[flush_type];
539
540 /* Initialize the gstream buffer */
541 gstream.next_in = inbuf;
542 gstream.avail_in = inbuf_size;
543 gstream.zalloc = Z_NULL;
544 gstream.zfree = Z_NULL;
545 gstream.opaque = Z_NULL;
546
547 if (hist_bits == 0)
548 hist_bits = -15;
549 else
550 hist_bits = -hist_bits;
551
552 if (0 != deflateInit2(&gstream, level, Z_DEFLATED, hist_bits, 9, Z_DEFAULT_STRATEGY))
553 return 1;
554
555 BENCHMARK(start, time,
556 check = zlib_deflate_round(&gstream, outbuf, *outbuf_size, inbuf, inbuf_size,
557 in_block_size, level, flush_type));
558
559 *outbuf_size = gstream.total_out;
560 deflateEnd(&gstream);
561
562 return check;
563 }
564
565 int
isal_inflate_perf(uint8_t * inbuf,uint64_t inbuf_size,uint8_t * outbuf,uint64_t outbuf_size,uint8_t * filebuf,uint64_t file_size,int hist_bits,int time,struct perf * start)566 isal_inflate_perf(uint8_t *inbuf, uint64_t inbuf_size, uint8_t *outbuf, uint64_t outbuf_size,
567 uint8_t *filebuf, uint64_t file_size, int hist_bits, int time, struct perf *start)
568 {
569 struct inflate_state state;
570 int check;
571
572 /* Check that data decompresses */
573 check = isal_inflate_round(&state, inbuf, inbuf_size, outbuf, outbuf_size, hist_bits);
574 if (check || state.total_out != file_size || memcmp(outbuf, filebuf, file_size))
575 return 1;
576
577 BENCHMARK(start, time,
578 isal_inflate_round(&state, inbuf, inbuf_size, outbuf, outbuf_size, hist_bits));
579
580 return check;
581 }
582
583 int
isal_inflate_stateful_perf(uint8_t * inbuf,uint64_t inbuf_size,uint8_t * outbuf,uint64_t outbuf_size,uint8_t * filebuf,uint64_t file_size,uint64_t in_block_size,int hist_bits,int time,struct perf * start,uint8_t * dict_buf,int dict_file_size)584 isal_inflate_stateful_perf(uint8_t *inbuf, uint64_t inbuf_size, uint8_t *outbuf,
585 uint64_t outbuf_size, uint8_t *filebuf, uint64_t file_size,
586 uint64_t in_block_size, int hist_bits, int time, struct perf *start,
587 uint8_t *dict_buf, int dict_file_size)
588 {
589 struct inflate_state state;
590 int check;
591
592 if (in_block_size == 0)
593 in_block_size = inbuf_size;
594
595 check = isal_inflate_stateful_round(&state, inbuf, inbuf_size, in_block_size, outbuf,
596 outbuf_size, hist_bits, dict_buf, dict_file_size);
597 if (check || state.total_out != file_size || memcmp(outbuf, filebuf, file_size))
598 return 1;
599
600 BENCHMARK(start, time,
601 isal_inflate_stateful_round(&state, inbuf, inbuf_size, in_block_size, outbuf,
602 outbuf_size, hist_bits, dict_buf, dict_file_size));
603
604 return 0;
605 }
606
607 int
zlib_inflate_perf(uint8_t * inbuf,uint64_t inbuf_size,uint8_t * outbuf,uint64_t outbuf_size,uint8_t * filebuf,uint64_t file_size,int hist_bits,int time,struct perf * start)608 zlib_inflate_perf(uint8_t *inbuf, uint64_t inbuf_size, uint8_t *outbuf, uint64_t outbuf_size,
609 uint8_t *filebuf, uint64_t file_size, int hist_bits, int time, struct perf *start)
610 {
611 int check;
612 z_stream gstream;
613
614 gstream.next_in = inbuf;
615 gstream.avail_in = inbuf_size;
616 gstream.zalloc = Z_NULL;
617 gstream.zfree = Z_NULL;
618 gstream.opaque = Z_NULL;
619
620 if (hist_bits == 0)
621 hist_bits = -15;
622 else
623 hist_bits = -hist_bits;
624
625 if (0 != inflateInit2(&gstream, hist_bits))
626 return 1;
627
628 check = zlib_inflate_round(&gstream, inbuf, inbuf_size, outbuf, outbuf_size);
629 if (check || gstream.total_out != file_size || memcmp(outbuf, filebuf, file_size))
630 return 1;
631
632 BENCHMARK(start, time,
633 zlib_inflate_round(&gstream, inbuf, inbuf_size, outbuf, outbuf_size));
634
635 inflateEnd(&gstream);
636 return 0;
637 }
638
639 int
main(int argc,char * argv[])640 main(int argc, char *argv[])
641 {
642 FILE *in = NULL;
643 FILE *dict_fn = NULL;
644 unsigned char *compressbuf, *decompbuf, *filebuf;
645 char *outfile = NULL;
646 int i, c, ret = 0;
647 int dict_file_size = 0;
648 uint8_t *dict_buf = NULL;
649 uint64_t decompbuf_size, compressbuf_size;
650 uint64_t block_count;
651
652 struct compress_strategy compression_queue[COMPRESSION_QUEUE_LIMIT];
653
654 int compression_queue_size = 0;
655 struct compress_strategy compress_strat;
656 struct inflate_modes inflate_strat = { 0 };
657 struct perf_info info;
658 init_perf_info(&info);
659
660 while ((c = getopt(argc, argv, OPTARGS)) != -1) {
661 switch (c) {
662 case 'l':
663 if (compression_queue_size >= COMPRESSION_QUEUE_LIMIT) {
664 printf("Too many levels specified");
665 exit(0);
666 }
667
668 compress_strat.mode = ISAL_STATELESS;
669 compress_strat.level = atoi(optarg);
670 if (compress_strat.level > ISAL_DEF_MAX_LEVEL) {
671 printf("Unsupported isa-l compression level\n");
672 exit(0);
673 }
674
675 compression_queue[compression_queue_size] = compress_strat;
676 compression_queue_size++;
677 break;
678 case 'f':
679 if (compression_queue_size >= COMPRESSION_QUEUE_LIMIT) {
680 printf("Too many levels specified");
681 exit(0);
682 }
683
684 compress_strat.mode = ISAL_STATEFUL;
685 compress_strat.level = atoi(optarg);
686 if (compress_strat.level > ISAL_DEF_MAX_LEVEL) {
687 printf("Unsupported isa-l compression level\n");
688 exit(0);
689 }
690
691 compression_queue[compression_queue_size] = compress_strat;
692 compression_queue_size++;
693 break;
694 case 'z':
695 if (compression_queue_size >= COMPRESSION_QUEUE_LIMIT) {
696 printf("Too many levels specified");
697 exit(0);
698 }
699
700 compress_strat.mode = ZLIB;
701 compress_strat.level = atoi(optarg);
702 if (compress_strat.level > Z_BEST_COMPRESSION) {
703 printf("Unsupported zlib compression level\n");
704 exit(0);
705 }
706 compression_queue[compression_queue_size] = compress_strat;
707 compression_queue_size++;
708 break;
709 case 'i':
710 info.inflate_time = atoi(optarg);
711 if (info.inflate_time < 0)
712 usage();
713 break;
714 case 'd':
715 info.deflate_time = atoi(optarg);
716 if (info.deflate_time < 0)
717 usage();
718 break;
719 case 'D':
720 dict_fn = fopen(optarg, "rb");
721 if (!dict_fn) {
722 printf("Can't open dictionary for reading\n");
723 exit(0);
724 }
725 dict_file_size = get_filesize(dict_fn);
726 dict_buf = malloc(dict_file_size);
727 if (dict_buf == NULL || dict_file_size == 0) {
728 printf("Can't allocate mem for dictionary buffer\n");
729 exit(0);
730 }
731 if (dict_file_size != fread(dict_buf, 1, dict_file_size, dict_fn)) {
732 printf("Couldn't read all of dictionary file\n");
733 exit(0);
734 }
735 fclose(dict_fn);
736 break;
737 case 's':
738 inflate_strat.stateful = 1;
739 break;
740 case 't':
741 inflate_strat.stateless = 1;
742 break;
743 case 'u':
744 inflate_strat.zlib = 1;
745 break;
746 case 'b':
747 inflate_strat.stateful = 1;
748 info.inblock_size = atoi(optarg);
749 break;
750 case 'y':
751 info.flush_type = atoi(optarg);
752 if (info.flush_type != NO_FLUSH && info.flush_type != SYNC_FLUSH &&
753 info.flush_type != FULL_FLUSH) {
754 printf("Unsupported flush type\n");
755 exit(0);
756 }
757 break;
758
759 case 'w':
760 info.hist_bits = atoi(optarg);
761 if (info.hist_bits > 15 || info.hist_bits < 9)
762 usage();
763 break;
764 case 'o':
765 outfile = optarg;
766 break;
767 case 'h':
768 default:
769 usage();
770 break;
771 }
772 }
773
774 if (optind >= argc)
775 usage();
776
777 if (!inflate_strat.stateless && !inflate_strat.stateful && !inflate_strat.zlib) {
778 if (info.inblock_size == 0)
779 inflate_strat.stateless = 1;
780 else
781 inflate_strat.stateful = 1;
782 }
783
784 /* Allocate space for entire input file and output
785 * (assuming some possible expansion on output size)
786 */
787 info.file_name = argv[optind];
788 in = fopen(info.file_name, "rb");
789 if (NULL == in) {
790 printf("Error: Can not find file %s\n", info.file_name);
791 exit(0);
792 }
793
794 info.file_size = get_filesize(in);
795 if (info.file_size == 0) {
796 printf("Error: input file has 0 size\n");
797 exit(0);
798 }
799
800 decompbuf_size = info.file_size;
801
802 if (compression_queue_size == 0) {
803 if (info.inblock_size == 0)
804 compression_queue[0].mode = ISAL_STATELESS;
805 else
806 compression_queue[0].mode = ISAL_STATEFUL;
807 compression_queue[0].level = 1;
808 compression_queue_size = 1;
809 }
810
811 filebuf = malloc(info.file_size);
812 if (filebuf == NULL) {
813 fprintf(stderr, "Can't allocate temp buffer memory\n");
814 exit(0);
815 }
816
817 block_count = 1;
818 if (info.flush_type > 0)
819 block_count = (info.file_size + info.inblock_size - 1) / info.inblock_size;
820
821 /* Way overestimate likely compressed size to handle bad type 0 and
822 * small block_size case */
823 compressbuf_size = block_count * ISAL_DEF_MAX_HDR_SIZE + 2 * info.file_size;
824 if (compressbuf_size >= MAX_COMPRESS_BUF_SIZE)
825 compressbuf_size = MAX_COMPRESS_BUF_SIZE;
826
827 compressbuf = malloc(compressbuf_size);
828 if (compressbuf == NULL) {
829 fprintf(stderr, "Can't allocate input buffer memory\n");
830 exit(0);
831 }
832
833 decompbuf = malloc(decompbuf_size);
834 if (decompbuf == NULL) {
835 fprintf(stderr, "Can't allocate output buffer memory\n");
836 exit(0);
837 }
838
839 if (info.file_size != fread(filebuf, 1, info.file_size, in)) {
840 fprintf(stderr, "Could not read in all input\n");
841 exit(0);
842 }
843 fclose(in);
844
845 for (i = 0; i < compression_queue_size; i++) {
846 if (i > 0)
847 printf("\n\n");
848
849 info.strategy = compression_queue[i];
850 print_perf_info_line(&info);
851
852 info.deflate_size = compressbuf_size;
853
854 if (dict_file_size != 0) {
855 info.strategy.mode = ISAL_WITH_DICTIONARY;
856 ret = isal_deflate_dict_perf(
857 compressbuf, &info.deflate_size, filebuf, info.file_size,
858 compression_queue[i].level, info.flush_type, info.hist_bits,
859 info.deflate_time, &info.start, dict_buf, dict_file_size);
860 } else if (info.strategy.mode == ISAL_STATELESS)
861 ret = isal_deflate_perf(compressbuf, &info.deflate_size, filebuf,
862 info.file_size, compression_queue[i].level,
863 info.flush_type, info.hist_bits, info.deflate_time,
864 &info.start);
865
866 else if (info.strategy.mode == ISAL_STATEFUL)
867 ret = isal_deflate_stateful_perf(
868 compressbuf, &info.deflate_size, filebuf, info.file_size,
869 compression_queue[i].level, info.flush_type, info.inblock_size,
870 info.hist_bits, info.deflate_time, &info.start);
871 else if (info.strategy.mode == ZLIB)
872 ret = zlib_deflate_perf(compressbuf, &info.deflate_size, filebuf,
873 info.file_size, compression_queue[i].level,
874 info.flush_type, info.inblock_size, info.hist_bits,
875 info.deflate_time, &info.start);
876 if (ret) {
877 printf(" Error in compression\n");
878 continue;
879 }
880
881 print_file_line(&info);
882 printf("\n");
883 print_deflate_perf_line(&info);
884 printf("\n");
885
886 if (outfile != NULL && i + 1 == compression_queue_size) {
887 FILE *out = fopen(outfile, "wb");
888
889 if (out == NULL) {
890 fprintf(stderr, "Could not write to the output file \"%s\"\n",
891 outfile);
892 exit(0);
893 }
894 fwrite(compressbuf, 1, info.deflate_size, out);
895 fclose(out);
896 }
897
898 if (info.inflate_time == 0)
899 continue;
900
901 if (inflate_strat.stateless) {
902 if (dict_file_size != 0)
903 continue;
904
905 info.inflate_mode = ISAL_STATELESS;
906 ret = isal_inflate_perf(compressbuf, info.deflate_size, decompbuf,
907 decompbuf_size, filebuf, info.file_size,
908 info.hist_bits, info.inflate_time, &info.start);
909 if (ret)
910 printf(" Error in isal stateless inflate\n");
911 else
912 print_inflate_perf_line(&info);
913 }
914
915 if (inflate_strat.stateful) {
916 info.inflate_mode =
917 (dict_file_size == 0) ? ISAL_STATEFUL : ISAL_WITH_DICTIONARY;
918
919 ret = isal_inflate_stateful_perf(
920 compressbuf, info.deflate_size, decompbuf, decompbuf_size, filebuf,
921 info.file_size, info.inblock_size, info.hist_bits,
922 info.inflate_time, &info.start, dict_buf, dict_file_size);
923
924 if (ret)
925 printf(" Error in isal stateful inflate\n");
926 else
927 print_inflate_perf_line(&info);
928 }
929
930 if (inflate_strat.zlib) {
931 info.inflate_mode = ZLIB;
932 ret = zlib_inflate_perf(compressbuf, info.deflate_size, decompbuf,
933 decompbuf_size, filebuf, info.file_size,
934 info.hist_bits, info.inflate_time, &info.start);
935 if (ret)
936 printf(" Error in zlib inflate\n");
937 else
938 print_inflate_perf_line(&info);
939 }
940 }
941
942 free(compressbuf);
943 free(decompbuf);
944 free(filebuf);
945 if (dict_buf != NULL)
946 free(dict_buf);
947 return 0;
948 }
949