]>
Commit | Line | Data |
---|---|---|
224ce89b WB |
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 | ||
f91f0fd5 | 30 | #define _FILE_OFFSET_BITS 64 |
224ce89b WB |
31 | #include <stdio.h> |
32 | #include <stdlib.h> | |
33 | #include <string.h> | |
34 | #include <getopt.h> | |
35 | #include "igzip_lib.h" | |
36 | #include "test.h" | |
37 | ||
38 | #define MIN_BUF_SIZE (4 * 1024) | |
39 | #define MIN_TEST_LOOPS 10 | |
40 | #ifndef RUN_MEM_SIZE | |
41 | # define RUN_MEM_SIZE 500000000 | |
42 | #endif | |
43 | ||
44 | #define DEFAULT_SEG_SIZE (512 * 1024) | |
45 | #define DEFAULT_SAMPLE_SIZE (32 * 1024) | |
46 | ||
47 | int usage(void) | |
48 | { | |
49 | fprintf(stderr, | |
50 | "Usage: igzip_semi_dynamic [options] <infile>\n" | |
51 | " -h help\n" | |
52 | " -v (don't) validate output by inflate and compare\n" | |
224ce89b WB |
53 | " -t <type> 1:stateless 0:(default)stateful\n" |
54 | " -c <size> chunk size default=%d\n" | |
55 | " -s <size> sample size default=%d\n" | |
56 | " -o <file> output file\n", DEFAULT_SEG_SIZE, DEFAULT_SAMPLE_SIZE); | |
57 | exit(0); | |
58 | } | |
59 | ||
60 | int str_to_i(char *s) | |
61 | { | |
62 | #define ARG_MAX 32 | |
63 | ||
64 | int i = atoi(s); | |
65 | int len = strnlen(s, ARG_MAX); | |
66 | if (len < 2 || len == ARG_MAX) | |
67 | return i; | |
68 | ||
69 | switch (s[len - 1]) { | |
70 | case 'k': | |
71 | i *= 1024; | |
72 | break; | |
73 | case 'K': | |
74 | i *= 1000; | |
75 | break; | |
76 | case 'm': | |
77 | i *= (1024 * 1024); | |
78 | break; | |
79 | case 'M': | |
80 | i *= (1000 * 1000); | |
81 | break; | |
82 | case 'g': | |
83 | i *= (1024 * 1024 * 1024); | |
84 | break; | |
85 | case 'G': | |
86 | i *= (1000 * 1000 * 1000); | |
87 | break; | |
88 | } | |
89 | return i; | |
90 | } | |
91 | ||
f91f0fd5 TL |
92 | void semi_dyn_stateless_perf(struct isal_zstream *stream, uint8_t * inbuf, |
93 | uint64_t infile_size, uint8_t * outbuf, uint64_t outbuf_size, | |
94 | int segment_size, int hist_size) | |
224ce89b | 95 | { |
f91f0fd5 TL |
96 | struct isal_huff_histogram histogram; |
97 | struct isal_hufftables hufftable; | |
98 | ||
99 | isal_deflate_stateless_init(stream); | |
100 | stream->end_of_stream = 0; | |
101 | stream->flush = FULL_FLUSH; | |
102 | stream->next_in = inbuf; | |
103 | stream->next_out = outbuf; | |
104 | int remaining = infile_size; | |
105 | int chunk_size = segment_size; | |
106 | ||
107 | while (remaining > 0) { | |
108 | // Generate custom hufftables on sample | |
109 | memset(&histogram, 0, sizeof(struct isal_huff_histogram)); | |
110 | if (remaining < segment_size * 2) { | |
111 | chunk_size = remaining; | |
112 | stream->end_of_stream = 1; | |
113 | } | |
114 | int hist_rem = (hist_size > chunk_size) ? chunk_size : hist_size; | |
115 | isal_update_histogram(stream->next_in, hist_rem, &histogram); | |
116 | ||
117 | if (hist_rem == chunk_size) | |
118 | isal_create_hufftables_subset(&hufftable, &histogram); | |
119 | else | |
120 | isal_create_hufftables(&hufftable, &histogram); | |
121 | ||
122 | // Compress with custom table | |
123 | stream->avail_in = chunk_size; | |
124 | stream->avail_out = chunk_size + 8 * (1 + (chunk_size >> 16)); | |
125 | stream->hufftables = &hufftable; | |
126 | remaining -= chunk_size; | |
127 | isal_deflate_stateless(stream); | |
128 | if (stream->avail_in != 0) | |
129 | break; | |
130 | } | |
131 | } | |
224ce89b | 132 | |
f91f0fd5 TL |
133 | void semi_dyn_stateful_perf(struct isal_zstream *stream, uint8_t * inbuf, |
134 | uint64_t infile_size, uint8_t * outbuf, uint64_t outbuf_size, | |
135 | int segment_size, int hist_size) | |
136 | { | |
137 | struct isal_huff_histogram histogram; | |
138 | struct isal_hufftables hufftable; | |
139 | ||
140 | isal_deflate_init(stream); | |
141 | stream->end_of_stream = 0; | |
142 | stream->flush = SYNC_FLUSH; | |
143 | stream->next_in = inbuf; | |
144 | stream->next_out = outbuf; | |
145 | stream->avail_out = outbuf_size; | |
146 | int remaining = infile_size; | |
147 | int chunk_size = segment_size; | |
148 | ||
149 | while (remaining > 0) { | |
150 | // Generate custom hufftables on sample | |
151 | memset(&histogram, 0, sizeof(struct isal_huff_histogram)); | |
152 | if (remaining < segment_size * 2) { | |
153 | chunk_size = remaining; | |
154 | stream->end_of_stream = 1; | |
155 | } | |
156 | int hist_rem = (hist_size > chunk_size) ? chunk_size : hist_size; | |
157 | isal_update_histogram(stream->next_in, hist_rem, &histogram); | |
158 | ||
159 | if (hist_rem == chunk_size) | |
160 | isal_create_hufftables_subset(&hufftable, &histogram); | |
161 | else | |
162 | isal_create_hufftables(&hufftable, &histogram); | |
163 | ||
164 | // Compress with custom table | |
165 | stream->avail_in = chunk_size; | |
166 | stream->hufftables = &hufftable; | |
167 | remaining -= chunk_size; | |
168 | isal_deflate(stream); | |
169 | if (stream->internal_state.state != ZSTATE_NEW_HDR) | |
170 | break; | |
171 | } | |
224ce89b WB |
172 | } |
173 | ||
174 | int main(int argc, char *argv[]) | |
175 | { | |
176 | FILE *in = stdin, *out = NULL; | |
177 | unsigned char *inbuf, *outbuf; | |
f91f0fd5 TL |
178 | int i = 0, c; |
179 | uint64_t infile_size, outbuf_size; | |
224ce89b WB |
180 | int segment_size = DEFAULT_SEG_SIZE; |
181 | int sample_size = DEFAULT_SAMPLE_SIZE; | |
182 | int check_output = 1; | |
f91f0fd5 | 183 | int do_stateless = 0, do_stateful = 1; |
224ce89b WB |
184 | int ret = 0; |
185 | char *out_file_name = NULL; | |
186 | struct isal_zstream stream; | |
224ce89b | 187 | |
f91f0fd5 | 188 | while ((c = getopt(argc, argv, "vht:c:s:o:")) != -1) { |
224ce89b WB |
189 | switch (c) { |
190 | case 'v': | |
191 | check_output ^= 1; | |
192 | break; | |
193 | case 't': | |
194 | if (atoi(optarg) == 1) { | |
195 | do_stateful = 0; | |
196 | do_stateless = 1; | |
197 | } | |
198 | break; | |
199 | case 'c': | |
200 | segment_size = str_to_i(optarg); | |
201 | break; | |
202 | case 's': | |
203 | sample_size = str_to_i(optarg); | |
204 | break; | |
205 | case 'o': | |
206 | out_file_name = optarg; | |
207 | break; | |
224ce89b WB |
208 | case 'h': |
209 | default: | |
210 | usage(); | |
211 | break; | |
212 | } | |
213 | } | |
214 | ||
215 | // Open input file | |
216 | if (optind < argc) { | |
217 | if (!(in = fopen(argv[optind], "rb"))) { | |
218 | fprintf(stderr, "Can't open %s for reading\n", argv[optind]); | |
219 | exit(1); | |
220 | } | |
221 | } else | |
222 | usage(); | |
223 | ||
224 | // Optionally open output file | |
225 | if (out_file_name != NULL) { | |
226 | if (!(out = fopen(out_file_name, "wb"))) { | |
227 | fprintf(stderr, "Can't open %s for writing\n", out_file_name); | |
228 | exit(1); | |
229 | } | |
230 | } | |
231 | ||
232 | printf("Window Size: %d K\n", IGZIP_HIST_SIZE / 1024); | |
233 | ||
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 | if (infile_size == 0) { | |
240 | printf("Input file has zero length\n"); | |
241 | usage(); | |
242 | } | |
243 | ||
224ce89b WB |
244 | outbuf_size = infile_size * 1.30 > MIN_BUF_SIZE ? infile_size * 1.30 : MIN_BUF_SIZE; |
245 | ||
246 | if (NULL == (inbuf = malloc(infile_size))) { | |
247 | fprintf(stderr, "Can't allocate input buffer memory\n"); | |
248 | exit(0); | |
249 | } | |
250 | if (NULL == (outbuf = malloc(outbuf_size))) { | |
251 | fprintf(stderr, "Can't allocate output buffer memory\n"); | |
252 | exit(0); | |
253 | } | |
254 | ||
255 | int hist_size = sample_size > segment_size ? segment_size : sample_size; | |
256 | ||
257 | printf("semi-dynamic sample=%d segment=%d %s\n", hist_size, segment_size, | |
258 | do_stateful ? "stateful" : "stateless"); | |
f91f0fd5 | 259 | printf("igzip_file_perf: %s\n", argv[optind]); |
224ce89b WB |
260 | |
261 | // Read complete input file into buffer | |
262 | stream.avail_in = (uint32_t) fread(inbuf, 1, infile_size, in); | |
263 | if (stream.avail_in != infile_size) { | |
264 | fprintf(stderr, "Couldn't fit all of input file into buffer\n"); | |
265 | exit(0); | |
266 | } | |
267 | ||
f91f0fd5 | 268 | struct perf start; |
224ce89b WB |
269 | |
270 | if (do_stateful) { | |
f91f0fd5 TL |
271 | BENCHMARK(&start, BENCHMARK_TIME, |
272 | semi_dyn_stateful_perf(&stream, inbuf, infile_size, outbuf, | |
273 | outbuf_size, segment_size, hist_size) | |
274 | ); | |
224ce89b WB |
275 | } |
276 | ||
277 | if (do_stateless) { | |
f91f0fd5 TL |
278 | BENCHMARK(&start, BENCHMARK_TIME, |
279 | semi_dyn_stateless_perf(&stream, inbuf, infile_size, outbuf, | |
280 | outbuf_size, segment_size, hist_size)); | |
224ce89b WB |
281 | } |
282 | ||
283 | if (stream.avail_in != 0) { | |
284 | printf("Could not compress all of inbuf\n"); | |
285 | ret = 1; | |
286 | } | |
287 | ||
f91f0fd5 | 288 | printf(" file %s - in_size=%lu out_size=%d iter=%d ratio=%3.1f%%\n", argv[optind], |
224ce89b WB |
289 | infile_size, stream.total_out, i, 100.0 * stream.total_out / infile_size); |
290 | ||
f91f0fd5 TL |
291 | printf("igzip_semi_dyn_file: "); |
292 | perf_print(start, (long long)infile_size); | |
224ce89b WB |
293 | |
294 | if (out != NULL) { | |
295 | printf("writing %s\n", out_file_name); | |
296 | fwrite(outbuf, 1, stream.total_out, out); | |
297 | fclose(out); | |
298 | } | |
299 | ||
300 | fclose(in); | |
301 | ||
302 | if (check_output) { | |
303 | unsigned char *inflate_buf; | |
304 | struct inflate_state istate; | |
305 | ||
306 | if (NULL == (inflate_buf = malloc(infile_size))) { | |
307 | fprintf(stderr, "Can't allocate reconstruct buffer memory\n"); | |
308 | exit(0); | |
309 | } | |
310 | isal_inflate_init(&istate); | |
311 | istate.next_in = outbuf; | |
312 | istate.avail_in = stream.total_out; | |
313 | istate.next_out = inflate_buf; | |
314 | istate.avail_out = infile_size; | |
315 | int check = isal_inflate(&istate); | |
316 | ||
317 | if (memcmp(inflate_buf, inbuf, infile_size)) { | |
318 | printf("inflate check Fail\n"); | |
319 | printf(" ret %d total_inflate=%d\n", check, istate.total_out); | |
320 | for (i = 0; i < infile_size; i++) { | |
321 | if (inbuf[i] != inflate_buf[i]) { | |
322 | printf(" first diff at offset=%d\n", i); | |
323 | break; | |
324 | } | |
325 | } | |
326 | ret = 1; | |
327 | } else | |
328 | printf("inflate check Pass\n"); | |
329 | free(inflate_buf); | |
330 | } | |
331 | ||
332 | printf("End of igzip_semi_dyn_file_perf\n\n"); | |
333 | return ret; | |
334 | } |