xref: /isa-l/igzip/igzip_file_perf.c (revision 699bb5bd3fd0b25ac5f39b75d039ca40362f5051)
1 /**********************************************************************
2   Copyright(c) 2011-2016 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 <string.h>
35 #include <getopt.h>
36 #include "igzip_lib.h"
37 #include "test.h"
38 
39 #define BUF_SIZE 1024
40 
41 int level_size_buf[10] = {
42 #ifdef ISAL_DEF_LVL0_DEFAULT
43 	ISAL_DEF_LVL0_DEFAULT,
44 #else
45 	0,
46 #endif
47 #ifdef ISAL_DEF_LVL1_DEFAULT
48 	ISAL_DEF_LVL1_DEFAULT,
49 #else
50 	0,
51 #endif
52 #ifdef ISAL_DEF_LVL2_DEFAULT
53 	ISAL_DEF_LVL2_DEFAULT,
54 #else
55 	0,
56 #endif
57 #ifdef ISAL_DEF_LVL3_DEFAULT
58 	ISAL_DEF_LVL3_DEFAULT,
59 #else
60 	0,
61 #endif
62 #ifdef ISAL_DEF_LVL4_DEFAULT
63 	ISAL_DEF_LVL4_DEFAULT,
64 #else
65 	0,
66 #endif
67 #ifdef ISAL_DEF_LVL5_DEFAULT
68 	ISAL_DEF_LVL5_DEFAULT,
69 #else
70 	0,
71 #endif
72 #ifdef ISAL_DEF_LVL6_DEFAULT
73 	ISAL_DEF_LVL6_DEFAULT,
74 #else
75 	0,
76 #endif
77 #ifdef ISAL_DEF_LVL7_DEFAULT
78 	ISAL_DEF_LVL7_DEFAULT,
79 #else
80 	0,
81 #endif
82 #ifdef ISAL_DEF_LVL8_DEFAULT
83 	ISAL_DEF_LVL8_DEFAULT,
84 #else
85 	0,
86 #endif
87 #ifdef ISAL_DEF_LVL9_DEFAULT
88 	ISAL_DEF_LVL9_DEFAULT,
89 #else
90 	0,
91 #endif
92 };
93 
94 int usage(void)
95 {
96 	fprintf(stderr,
97 		"Usage: igzip_file_perf [options] <infile>\n"
98 		"  -h        help\n"
99 		"  -X        use compression level X with 0 <= X <= 1\n"
100 		"  -b <size> input buffer size, 0 buffers all the input\n"
101 		"  -i <time> time in seconds to benchmark (at least 1)\n"
102 		"  -o <file> output file for compresed data\n"
103 		"  -d <file> dictionary file used by compression\n"
104 		"  -w <size> log base 2 size of history window, between 8 and 15\n");
105 
106 	exit(0);
107 }
108 
109 void deflate_perf(struct isal_zstream *stream, uint8_t * inbuf, size_t infile_size,
110 		  size_t inbuf_size, uint8_t * outbuf, size_t outbuf_size, int level,
111 		  uint8_t * level_buf, int level_size, uint32_t hist_bits, uint8_t * dictbuf,
112 		  size_t dictfile_size, struct isal_hufftables *hufftables_custom)
113 {
114 	int avail_in;
115 	isal_deflate_init(stream);
116 	if (dictbuf != NULL)
117 		isal_deflate_set_dict(stream, dictbuf, dictfile_size);
118 	stream->end_of_stream = 0;
119 	stream->flush = NO_FLUSH;
120 	stream->level = level;
121 	stream->level_buf = level_buf;
122 	stream->level_buf_size = level_size;
123 	stream->next_out = outbuf;
124 	stream->avail_out = outbuf_size;
125 	stream->next_in = inbuf;
126 	if (hufftables_custom != NULL)
127 		stream->hufftables = hufftables_custom;
128 	stream->hist_bits = hist_bits;
129 	avail_in = infile_size;
130 
131 	while (avail_in > 0) {
132 		stream->avail_in = avail_in >= inbuf_size ? inbuf_size : avail_in;
133 		avail_in -= inbuf_size;
134 
135 		if (avail_in <= 0)
136 			stream->end_of_stream = 1;
137 
138 		isal_deflate(stream);
139 
140 		if (stream->avail_in != 0)
141 			break;
142 	}
143 }
144 
145 int main(int argc, char *argv[])
146 {
147 	FILE *in = NULL, *out = NULL, *dict = NULL;
148 	unsigned char *inbuf, *outbuf, *level_buf = NULL, *dictbuf = NULL;
149 	int c, time = BENCHMARK_TIME, inbuf_size = 0;
150 	size_t infile_size, outbuf_size, dictfile_size;
151 	struct isal_huff_histogram histogram;
152 	struct isal_hufftables hufftables_custom;
153 	int level = 0, level_size = 0;
154 	char *in_file_name = NULL, *out_file_name = NULL, *dict_file_name = NULL;
155 	uint32_t hist_bits = 0;
156 	struct isal_zstream stream;
157 
158 	while ((c = getopt(argc, argv, "h0123456789i:b:o:d:w:")) != -1) {
159 		if (c >= '0' && c <= '9') {
160 			if (c > '0' + ISAL_DEF_MAX_LEVEL)
161 				usage();
162 			else {
163 				level = c - '0';
164 				level_size = level_size_buf[level];
165 			}
166 			continue;
167 		}
168 
169 		switch (c) {
170 		case 'o':
171 			out_file_name = optarg;
172 			break;
173 		case 'd':
174 			dict_file_name = optarg;
175 			break;
176 		case 'i':
177 			time = atoi(optarg);
178 			if (time < 1)
179 				usage();
180 			break;
181 		case 'b':
182 			inbuf_size = atoi(optarg);
183 			break;
184 		case 'w':
185 			hist_bits = atoi(optarg);
186 			if (hist_bits > 15 || hist_bits < 8)
187 				usage();
188 			break;
189 		case 'h':
190 		default:
191 			usage();
192 			break;
193 		}
194 	}
195 
196 	if (optind < argc) {
197 		in_file_name = argv[optind];
198 		in = fopen(in_file_name, "rb");
199 	} else
200 		usage();
201 
202 	if (!in) {
203 		fprintf(stderr, "Can't open %s for reading\n", in_file_name);
204 		exit(0);
205 	}
206 	if (out_file_name != NULL) {
207 		out = fopen(out_file_name, "wb");
208 		if (!out) {
209 			fprintf(stderr, "Can't open %s for writing\n", out_file_name);
210 			exit(0);
211 		}
212 		printf("outfile=%s\n", out_file_name);
213 	}
214 
215 	if (dict_file_name != NULL) {
216 		dict = fopen(dict_file_name, "rb");
217 		if (!dict) {
218 			fprintf(stderr, "Can't open %s for reading\n", dict_file_name);
219 			exit(0);
220 		}
221 		printf("outfile=%s\n", dict_file_name);
222 	}
223 
224 	if (hist_bits == 0)
225 		printf("Window Size: %d K\n", IGZIP_HIST_SIZE / 1024);
226 
227 	else if (hist_bits < 10)
228 		printf("Window Size: %.2f K\n", 1.0 * (1 << hist_bits) / 1024);
229 	else
230 		printf("Window Size: %d K\n", (1 << hist_bits) / 1024);
231 
232 	printf("igzip_file_perf: \n");
233 	fflush(0);
234 
235 	/* Allocate space for entire input file and output
236 	 * (assuming some possible expansion on output size)
237 	 */
238 	infile_size = get_filesize(in);
239 
240 	outbuf_size = 2 * infile_size + BUF_SIZE;
241 
242 	dictfile_size = (dict_file_name != NULL) ? get_filesize(dict) : 0;
243 
244 	inbuf = malloc(infile_size);
245 	if (inbuf == NULL) {
246 		fprintf(stderr, "Can't allocate input buffer memory\n");
247 		exit(0);
248 	}
249 	outbuf = malloc(outbuf_size);
250 	if (outbuf == NULL) {
251 		fprintf(stderr, "Can't allocate output buffer memory\n");
252 		exit(0);
253 	}
254 
255 	if (dictfile_size != 0) {
256 		dictbuf = malloc(dictfile_size);
257 		if (dictbuf == NULL) {
258 			fprintf(stderr, "Can't allocate dictionary buffer memory\n");
259 			exit(0);
260 		}
261 	}
262 
263 	if (level_size != 0) {
264 		level_buf = malloc(level_size);
265 		if (level_buf == NULL) {
266 			fprintf(stderr, "Can't allocate level buffer memory\n");
267 			exit(0);
268 		}
269 	}
270 
271 	inbuf_size = inbuf_size ? inbuf_size : infile_size;
272 
273 	printf("igzip_file_perf: %s\n", in_file_name);
274 
275 	/* Read complete input file into buffer */
276 	stream.avail_in = (uint32_t) fread(inbuf, 1, infile_size, in);
277 	if (stream.avail_in != infile_size) {
278 		fprintf(stderr, "Couldn't fit all of input file into buffer\n");
279 		exit(0);
280 	}
281 
282 	/* Read complete dictionary into buffer */
283 	if ((dictfile_size != 0) && (dictfile_size != fread(dictbuf, 1, dictfile_size, dict))) {
284 		fprintf(stderr, "Couldn't fit all of dictionary file into buffer\n");
285 		exit(0);
286 	}
287 
288 	struct perf start;
289 	BENCHMARK(&start, time,
290 		  deflate_perf(&stream, inbuf, infile_size, inbuf_size, outbuf, outbuf_size,
291 			       level, level_buf, level_size, hist_bits, dictbuf,
292 			       dictfile_size, NULL));
293 	if (stream.avail_in != 0) {
294 		fprintf(stderr, "Could not compress all of inbuf\n");
295 		exit(0);
296 	}
297 
298 	printf("  file %s - in_size=%lu out_size=%d ratio=%3.1f%%",
299 	       in_file_name, infile_size, stream.total_out,
300 	       100.0 * stream.total_out / infile_size);
301 
302 	if (level == 0) {
303 		memset(&histogram, 0, sizeof(histogram));
304 
305 		isal_update_histogram(inbuf, infile_size, &histogram);
306 		isal_create_hufftables(&hufftables_custom, &histogram);
307 
308 		deflate_perf(&stream, inbuf, infile_size, inbuf_size, outbuf, outbuf_size,
309 			     level, level_buf, level_size, hist_bits, dictbuf,
310 			     dictfile_size, &hufftables_custom);
311 
312 		printf(" ratio_custom=%3.1f%%", 100.0 * stream.total_out / infile_size);
313 	}
314 	printf("\n");
315 
316 	if (stream.avail_in != 0) {
317 		fprintf(stderr, "Could not compress all of inbuf\n");
318 		exit(0);
319 	}
320 
321 	printf("igzip_file: ");
322 	perf_print(start, (long long)infile_size);
323 
324 	if (argc > 2 && out) {
325 		printf("writing %s\n", out_file_name);
326 		fwrite(outbuf, 1, stream.total_out, out);
327 		fclose(out);
328 	}
329 
330 	fclose(in);
331 	printf("End of igzip_file_perf\n\n");
332 	fflush(0);
333 	return 0;
334 }
335