diff options
author | Mark Adler <madler@alumni.caltech.edu> | 2015-07-05 18:14:53 -0700 |
---|---|---|
committer | Mark Adler <madler@alumni.caltech.edu> | 2015-07-05 18:14:53 -0700 |
commit | 95698093f023852ca4365df307c19a1d7cfa3687 (patch) | |
tree | 743b907c5449f617343e8bec546eabbb650df0a8 | |
parent | 8a979f6c7986574e37316148cd8ca440c3bc08a3 (diff) | |
download | zlib-95698093f023852ca4365df307c19a1d7cfa3687.tar.gz zlib-95698093f023852ca4365df307c19a1d7cfa3687.tar.bz2 zlib-95698093f023852ca4365df307c19a1d7cfa3687.zip |
Improve speed of gzprintf() in transparent mode.
-rw-r--r-- | gzguts.h | 2 | ||||
-rw-r--r-- | gzlib.c | 2 | ||||
-rw-r--r-- | gzwrite.c | 110 | ||||
-rw-r--r-- | zlib.h | 7 |
4 files changed, 70 insertions, 51 deletions
@@ -170,7 +170,7 @@ typedef struct { | |||
170 | char *path; /* path or fd for error messages */ | 170 | char *path; /* path or fd for error messages */ |
171 | unsigned size; /* buffer size, zero if not allocated yet */ | 171 | unsigned size; /* buffer size, zero if not allocated yet */ |
172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ | 172 | unsigned want; /* requested buffer size, default is GZBUFSIZE */ |
173 | unsigned char *in; /* input buffer */ | 173 | unsigned char *in; /* input buffer (double-sized when writing) */ |
174 | unsigned char *out; /* output buffer (double-sized when reading) */ | 174 | unsigned char *out; /* output buffer (double-sized when reading) */ |
175 | int direct; /* 0 if processing gzip, 1 if transparent */ | 175 | int direct; /* 0 if processing gzip, 1 if transparent */ |
176 | /* just for reading */ | 176 | /* just for reading */ |
@@ -331,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) | |||
331 | return -1; | 331 | return -1; |
332 | 332 | ||
333 | /* check and set requested size */ | 333 | /* check and set requested size */ |
334 | if ((size << 1) < size) | ||
335 | return -1; /* need to be able to double it */ | ||
334 | if (size < 2) | 336 | if (size < 2) |
335 | size = 2; /* need two bytes to check magic header */ | 337 | size = 2; /* need two bytes to check magic header */ |
336 | state->want = size; | 338 | state->want = size; |
@@ -18,8 +18,8 @@ local int gz_init(state) | |||
18 | int ret; | 18 | int ret; |
19 | z_streamp strm = &(state->strm); | 19 | z_streamp strm = &(state->strm); |
20 | 20 | ||
21 | /* allocate input buffer */ | 21 | /* allocate input buffer (double size for gzprintf) */ |
22 | state->in = (unsigned char *)malloc(state->want); | 22 | state->in = (unsigned char *)malloc(state->want << 1); |
23 | if (state->in == NULL) { | 23 | if (state->in == NULL) { |
24 | gz_error(state, Z_MEM_ERROR, "out of memory"); | 24 | gz_error(state, Z_MEM_ERROR, "out of memory"); |
25 | return -1; | 25 | return -1; |
@@ -309,7 +309,8 @@ int ZEXPORT gzputs(file, str) | |||
309 | /* -- see zlib.h -- */ | 309 | /* -- see zlib.h -- */ |
310 | int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) | 310 | int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) |
311 | { | 311 | { |
312 | int size, len; | 312 | unsigned len, left; |
313 | char *next; | ||
313 | gz_statep state; | 314 | gz_statep state; |
314 | z_streamp strm; | 315 | z_streamp strm; |
315 | 316 | ||
@@ -334,39 +335,47 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) | |||
334 | return 0; | 335 | return 0; |
335 | } | 336 | } |
336 | 337 | ||
337 | /* consume whatever's left in the input buffer */ | 338 | /* do the printf() into the input buffer, put length in len -- the input |
338 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | 339 | buffer is double-sized just for this function, so there is guaranteed to |
339 | return 0; | 340 | be state->size bytes available after the current contents */ |
340 | 341 | if (strm->avail_in == 0) | |
341 | /* do the printf() into the input buffer, put length in len */ | 342 | strm->next_in = state->in; |
342 | size = (int)(state->size); | 343 | next = (char *)(strm->next_in + strm->avail_in); |
343 | state->in[size - 1] = 0; | 344 | next[state->size - 1] = 0; |
344 | #ifdef NO_vsnprintf | 345 | #ifdef NO_vsnprintf |
345 | # ifdef HAS_vsprintf_void | 346 | # ifdef HAS_vsprintf_void |
346 | (void)vsprintf((char *)(state->in), format, va); | 347 | (void)vsprintf(next, format, va); |
347 | for (len = 0; len < size; len++) | 348 | for (len = 0; len < state->size; len++) |
348 | if (state->in[len] == 0) break; | 349 | if (next[len] == 0) break; |
349 | # else | 350 | # else |
350 | len = vsprintf((char *)(state->in), format, va); | 351 | len = vsprintf(next, format, va); |
351 | # endif | 352 | # endif |
352 | #else | 353 | #else |
353 | # ifdef HAS_vsnprintf_void | 354 | # ifdef HAS_vsnprintf_void |
354 | (void)vsnprintf((char *)(state->in), size, format, va); | 355 | (void)vsnprintf(next, state->size, format, va); |
355 | len = strlen((char *)(state->in)); | 356 | len = strlen(next); |
356 | # else | 357 | # else |
357 | len = vsnprintf((char *)(state->in), size, format, va); | 358 | len = vsnprintf(next, state->size, format, va); |
358 | # endif | 359 | # endif |
359 | #endif | 360 | #endif |
360 | 361 | ||
361 | /* check that printf() results fit in buffer */ | 362 | /* check that printf() results fit in buffer */ |
362 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | 363 | if (len == 0 || len >= state->size || next[state->size - 1] != 0) |
363 | return 0; | 364 | return 0; |
364 | 365 | ||
365 | /* update buffer and position, defer compression until needed */ | 366 | /* update buffer and position, compress first half if past that */ |
366 | strm->avail_in = (unsigned)len; | 367 | strm->avail_in += len; |
367 | strm->next_in = state->in; | ||
368 | state->x.pos += len; | 368 | state->x.pos += len; |
369 | return len; | 369 | if (strm->avail_in >= state->size) { |
370 | left = strm->avail_in - state->size; | ||
371 | strm->avail_in = state->size; | ||
372 | if (gz_comp(state, Z_NO_FLUSH) == -1) | ||
373 | return 0; | ||
374 | memcpy(state->in, state->in + state->size, left); | ||
375 | strm->next_in = state->in; | ||
376 | strm->avail_in = left; | ||
377 | } | ||
378 | return (int)len; | ||
370 | } | 379 | } |
371 | 380 | ||
372 | int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) | 381 | int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) |
@@ -390,7 +399,8 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |||
390 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | 399 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, |
391 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | 400 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; |
392 | { | 401 | { |
393 | int size, len; | 402 | unsigned len, left; |
403 | char *next; | ||
394 | gz_statep state; | 404 | gz_statep state; |
395 | z_streamp strm; | 405 | z_streamp strm; |
396 | 406 | ||
@@ -419,44 +429,52 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | |||
419 | return 0; | 429 | return 0; |
420 | } | 430 | } |
421 | 431 | ||
422 | /* consume whatever's left in the input buffer */ | 432 | /* do the printf() into the input buffer, put length in len -- the input |
423 | if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) | 433 | buffer is double-sized just for this function, so there is guaranteed to |
424 | return 0; | 434 | be state->size bytes available after the current contents */ |
425 | 435 | if (strm->avail_in == 0) | |
426 | /* do the printf() into the input buffer, put length in len */ | 436 | strm->next_in = state->in; |
427 | size = (int)(state->size); | 437 | next = (char *)(strm->next_in + strm->avail_in); |
428 | state->in[size - 1] = 0; | 438 | next[state->size - 1] = 0; |
429 | #ifdef NO_snprintf | 439 | #ifdef NO_snprintf |
430 | # ifdef HAS_sprintf_void | 440 | # ifdef HAS_sprintf_void |
431 | sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | 441 | sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, |
432 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 442 | a13, a14, a15, a16, a17, a18, a19, a20); |
433 | for (len = 0; len < size; len++) | 443 | for (len = 0; len < size; len++) |
434 | if (state->in[len] == 0) break; | 444 | if (next[len] == 0) |
445 | break; | ||
435 | # else | 446 | # else |
436 | len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, | 447 | len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, |
437 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 448 | a12, a13, a14, a15, a16, a17, a18, a19, a20); |
438 | # endif | 449 | # endif |
439 | #else | 450 | #else |
440 | # ifdef HAS_snprintf_void | 451 | # ifdef HAS_snprintf_void |
441 | snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, | 452 | snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, |
442 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | 453 | a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
443 | len = strlen((char *)(state->in)); | 454 | len = strlen(next); |
444 | # else | 455 | # else |
445 | len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, | 456 | len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, |
446 | a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, | 457 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); |
447 | a19, a20); | ||
448 | # endif | 458 | # endif |
449 | #endif | 459 | #endif |
450 | 460 | ||
451 | /* check that printf() results fit in buffer */ | 461 | /* check that printf() results fit in buffer */ |
452 | if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) | 462 | if (len == 0 || len >= state->size || next[state->size - 1] != 0) |
453 | return 0; | 463 | return 0; |
454 | 464 | ||
455 | /* update buffer and position, defer compression until needed */ | 465 | /* update buffer and position, compress first half if past that */ |
456 | strm->avail_in = (unsigned)len; | 466 | strm->avail_in += len; |
457 | strm->next_in = state->in; | ||
458 | state->x.pos += len; | 467 | state->x.pos += len; |
459 | return len; | 468 | if (strm->avail_in >= state->size) { |
469 | left = strm->avail_in - state->size; | ||
470 | strm->avail_in = state->size; | ||
471 | if (gz_comp(state, Z_NO_FLUSH) == -1) | ||
472 | return 0; | ||
473 | memcpy(state->in, state->in + state->size, left); | ||
474 | strm->next_in = state->in; | ||
475 | strm->avail_in = left; | ||
476 | } | ||
477 | return (int)len; | ||
460 | } | 478 | } |
461 | 479 | ||
462 | #endif | 480 | #endif |
@@ -1291,10 +1291,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); | |||
1291 | default buffer size is 8192 bytes. This function must be called after | 1291 | default buffer size is 8192 bytes. This function must be called after |
1292 | gzopen() or gzdopen(), and before any other calls that read or write the | 1292 | gzopen() or gzdopen(), and before any other calls that read or write the |
1293 | file. The buffer memory allocation is always deferred to the first read or | 1293 | file. The buffer memory allocation is always deferred to the first read or |
1294 | write. Two buffers are allocated, either both of the specified size when | 1294 | write. Three times that size in buffer space is allocated. A larger buffer |
1295 | writing, or one of the specified size and the other twice that size when | 1295 | size of, for example, 64K or 128K bytes will noticeably increase the speed |
1296 | reading. A larger buffer size of, for example, 64K or 128K bytes will | 1296 | of decompression (reading). |
1297 | noticeably increase the speed of decompression (reading). | ||
1298 | 1297 | ||
1299 | The new buffer size also affects the maximum length for gzprintf(). | 1298 | The new buffer size also affects the maximum length for gzprintf(). |
1300 | 1299 | ||