Tighten deflateBound bounds.
This improves the non-default expansion from 14% down to 4% in most cases, and 13% in the remainder.
This commit is contained in:
parent
7fabcb5357
commit
4078713e3b
59
deflate.c
59
deflate.c
@ -674,36 +674,50 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================================================================
|
/* =========================================================================
|
||||||
* For the default windowBits of 15 and memLevel of 8, this function returns
|
* For the default windowBits of 15 and memLevel of 8, this function returns a
|
||||||
* a close to exact, as well as small, upper bound on the compressed size.
|
* close to exact, as well as small, upper bound on the compressed size. This
|
||||||
* They are coded as constants here for a reason--if the #define's are
|
* is an expansion of ~0.03%, plus a small constant.
|
||||||
* changed, then this function needs to be changed as well. The return
|
|
||||||
* value for 15 and 8 only works for those exact settings.
|
|
||||||
*
|
*
|
||||||
* For any setting other than those defaults for windowBits and memLevel,
|
* For any setting other than those defaults for windowBits and memLevel, one
|
||||||
* the value returned is a conservative worst case for the maximum expansion
|
* of two worst case bounds is returned. This is at most an expansion of ~4% or
|
||||||
* resulting from using fixed blocks instead of stored blocks, which deflate
|
* ~13%, plus a small constant.
|
||||||
* can emit on compressed data for some combinations of the parameters.
|
|
||||||
*
|
*
|
||||||
* This function could be more sophisticated to provide closer upper bounds for
|
* Both the 0.03% and 4% derive from the overhead of stored blocks. The first
|
||||||
* every combination of windowBits and memLevel. But even the conservative
|
* one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
|
||||||
* upper bound of about 14% expansion does not seem onerous for output buffer
|
* is for stored blocks of 127 bytes (the worst case memLevel == 1). The
|
||||||
* allocation.
|
* expansion results from five bytes of header for each stored block.
|
||||||
|
*
|
||||||
|
* The larger expansion of 13% results from a window size less than or equal to
|
||||||
|
* the symbols buffer size (windowBits <= memLevel + 7). In that case some of
|
||||||
|
* the data being compressed may have slid out of the sliding window, impeding
|
||||||
|
* a stored block from being emitted. Then the only choice is a fixed or
|
||||||
|
* dynamic block, where a fixed block limits the maximum expansion to 9 bits
|
||||||
|
* per 8-bit byte, plus 10 bits for every block. The smallest block size for
|
||||||
|
* which this can occur is 255 (memLevel == 2).
|
||||||
|
*
|
||||||
|
* Shifts are used to approximate divisions, for speed.
|
||||||
*/
|
*/
|
||||||
uLong ZEXPORT deflateBound(strm, sourceLen)
|
uLong ZEXPORT deflateBound(strm, sourceLen)
|
||||||
z_streamp strm;
|
z_streamp strm;
|
||||||
uLong sourceLen;
|
uLong sourceLen;
|
||||||
{
|
{
|
||||||
deflate_state *s;
|
deflate_state *s;
|
||||||
uLong complen, wraplen;
|
uLong fixedlen, storelen, wraplen;
|
||||||
|
|
||||||
/* conservative upper bound for compressed data */
|
/* upper bound for fixed blocks with 9-bit literals and length 255
|
||||||
complen = sourceLen +
|
(memLevel == 2, which is the lowest that may not use stored blocks) --
|
||||||
((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
|
~13% overhead plus a small constant */
|
||||||
|
fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
|
||||||
|
(sourceLen >> 9) + 4;
|
||||||
|
|
||||||
/* if can't get parameters, return conservative bound plus zlib wrapper */
|
/* upper bound for stored blocks with length 127 (memLevel == 1) --
|
||||||
|
~4% overhead plus a small constant */
|
||||||
|
storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
|
||||||
|
(sourceLen >> 11) + 7;
|
||||||
|
|
||||||
|
/* if can't get parameters, return larger bound plus a zlib wrapper */
|
||||||
if (deflateStateCheck(strm))
|
if (deflateStateCheck(strm))
|
||||||
return complen + 6;
|
return (fixedlen > storelen ? fixedlen : storelen) + 6;
|
||||||
|
|
||||||
/* compute wrapper length */
|
/* compute wrapper length */
|
||||||
s = strm->state;
|
s = strm->state;
|
||||||
@ -740,11 +754,12 @@ uLong ZEXPORT deflateBound(strm, sourceLen)
|
|||||||
wraplen = 6;
|
wraplen = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if not default parameters, return conservative bound */
|
/* if not default parameters, return one of the conservative bounds */
|
||||||
if (s->w_bits != 15 || s->hash_bits != 8 + 7)
|
if (s->w_bits != 15 || s->hash_bits != 8 + 7)
|
||||||
return complen + wraplen;
|
return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen;
|
||||||
|
|
||||||
/* default settings: return tight bound for that case */
|
/* default settings: return tight bound for that case -- ~0.03% overhead
|
||||||
|
plus a small constant */
|
||||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
||||||
(sourceLen >> 25) + 13 - 6 + wraplen;
|
(sourceLen >> 25) + 13 - 6 + wraplen;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user