BitInputStream: Optimize a bit to reach previous run times.
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/a0f55d9f Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/a0f55d9f Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/a0f55d9f Branch: refs/heads/master Commit: a0f55d9ff89a5cec2ccd4efc8200308b6dcf8a33 Parents: 96e34c6 Author: Thomas Meyer <tho...@m3y3r.de> Authored: Thu Jan 19 20:39:01 2017 +0100 Committer: Stefan Bodewig <bode...@apache.org> Committed: Sat Feb 4 18:56:59 2017 +0100 ---------------------------------------------------------------------- .../bzip2/BZip2CompressorInputStream.java | 45 ++++----- .../commons/compress/utils/BitInputStream.java | 97 ++++++++++++-------- 2 files changed, 80 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/a0f55d9f/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java index c1ed68f..348334f 100644 --- a/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java +++ b/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java @@ -307,7 +307,7 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements throw new IOException("bad block header"); } this.storedBlockCRC = bsGetInt(); - this.blockRandomised = bsR(1) == 1; + this.blockRandomised = bsR(bin, 1) == 1; /** * Allocate data here instead in constructor, so we do not allocate @@ -378,7 +378,7 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements * @return * @throws IOException */ - private int bsR(final int n) throws IOException { + private static int bsR(BitInputStream bin, final int n) throws IOException { long thech = bin.readBits(n); if (thech < 0) { throw new IOException("unexpected end of stream"); @@ -386,16 +386,16 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements return (int) thech; } - private boolean bsGetBit() throws IOException { - return bsR(1) != 0; + private static boolean bsGetBit(BitInputStream bin) throws IOException { + return bsR(bin, 1) != 0; } private char bsGetUByte() throws IOException { - return (char) bsR(8); + return (char) bsR(bin, 8); } private int bsGetInt() throws IOException { - return (int) bsR(32); + return (int) bsR(bin, 32); } /** @@ -440,6 +440,7 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements } private void recvDecodingTables() throws IOException { + final BitInputStream bin = this.bin; final Data dataShadow = this.data; final boolean[] inUse = dataShadow.inUse; final byte[] pos = dataShadow.recvDecodingTables_pos; @@ -450,7 +451,7 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements /* Receive the mapping table */ for (int i = 0; i < 16; i++) { - if (bsGetBit()) { + if (bsGetBit(bin)) { inUse16 |= 1 << i; } } @@ -460,7 +461,7 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements if ((inUse16 & (1 << i)) != 0) { final int i16 = i << 4; for (int j = 0; j < 16; j++) { - if (bsGetBit()) { + if (bsGetBit(bin)) { inUse[i16 + j] = true; } } @@ -469,14 +470,13 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements makeMaps(); final int alphaSize = this.nInUse + 2; - /* Now the selectors */ - final int nGroups = bsR(3); - final int nSelectors = bsR(15); + final int nGroups = bsR(bin, 3); + final int nSelectors = bsR(bin, 15); for (int i = 0; i < nSelectors; i++) { int j = 0; - while (bsGetBit()) { + while (bsGetBit(bin)) { j++; } selectorMtf[i] = (byte) j; @@ -503,11 +503,11 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements /* Now the coding tables */ for (int t = 0; t < nGroups; t++) { - int curr = bsR(5); + int curr = bsR(bin, 5); final char[] len_t = len[t]; for (int i = 0; i < alphaSize; i++) { - while (bsGetBit()) { - curr += bsGetBit() ? -1 : 1; + while (bsGetBit(bin)) { + curr += bsGetBit(bin) ? -1 : 1; } len_t[i] = (char) curr; } @@ -549,7 +549,8 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements } private void getAndMoveToFrontDecode() throws IOException { - this.origPtr = bsR(24); + final BitInputStream bin = this.bin; + this.origPtr = bsR(bin, 24); recvDecodingTables(); final Data dataShadow = this.data; @@ -610,10 +611,10 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements } int zn = minLens_zt; - int zvec = (int) bsR(zn); + int zvec = (int) bsR(bin, zn); while(zvec > limit_zt[zn]) { zn++; - zvec = (zvec << 1) | bsR(1); + zvec = (zvec << 1) | bsR(bin, 1); } nextSym = perm_zt[zvec - base_zt[zn]]; } @@ -664,10 +665,10 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements } int zn = minLens_zt; - int zvec = (int) bsR(zn); + int zvec = (int) bsR(bin, zn); while(zvec > limit_zt[zn]) { zn++; - zvec = (zvec << 1) | (int) bsR(1); + zvec = (zvec << 1) | (int) bsR(bin, 1); } nextSym = perm_zt[zvec - base_zt[zn]]; } @@ -681,10 +682,10 @@ public class BZip2CompressorInputStream extends CompressorInputStream implements final int zt = dataShadow.selector[groupNo] & 0xff; final int[] limit_zt = dataShadow.limit[zt]; int zn = dataShadow.minLens[zt]; - int zvec = bsR(zn); + int zvec = bsR(bin, zn); while (zvec > limit_zt[zn]) { zn++; - zvec = (zvec << 1) | (int) bsR(1); + zvec = (zvec << 1) | (int) bsR(bin, 1); } return dataShadow.perm[zt][zvec - dataShadow.base[zt][zn]]; http://git-wip-us.apache.org/repos/asf/commons-compress/blob/a0f55d9f/src/main/java/org/apache/commons/compress/utils/BitInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java index 35773b7..d933b0d 100644 --- a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java +++ b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java @@ -53,12 +53,12 @@ public class BitInputStream implements Closeable { this.in = in; this.byteOrder = byteOrder; } - + @Override public void close() throws IOException { in.close(); } - + /** * Clears the cache of bits that have been read from the * underlying stream but not yet provided via {@link #readBits}. @@ -82,56 +82,73 @@ public class BitInputStream implements Closeable { if (count < 0 || count > MAXIMUM_CACHE_SIZE) { throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE); } - while (bitsCachedSize < count && bitsCachedSize < 57) { - final long nextByte = in.read(); - if (nextByte < 0) { - return nextByte; - } + if(ensureCache(count)) + return -1; + + if (bitsCachedSize < count) { + return processBitsGreater57(count); + } else { + final long bitsOut; if (byteOrder == ByteOrder.LITTLE_ENDIAN) { - bitsCached |= (nextByte << bitsCachedSize); + bitsOut = (bitsCached & MASKS[count]); + bitsCached >>>= count; } else { - bitsCached <<= 8; - bitsCached |= nextByte; + bitsOut = (bitsCached >> (bitsCachedSize - count)) & MASKS[count]; } - bitsCachedSize += 8; + bitsCachedSize -= count; + return bitsOut; } + } + + private long processBitsGreater57(final int count) throws IOException { + final long bitsOut; int overflowBits = 0; long overflow = 0l; - if (bitsCachedSize < count) { - // bitsCachedSize >= 57 and left-shifting it 8 bits would cause an overflow - int bitsToAddCount = count - bitsCachedSize; - overflowBits = 8 - bitsToAddCount; + + // bitsCachedSize >= 57 and left-shifting it 8 bits would cause an overflow + int bitsToAddCount = count - bitsCachedSize; + overflowBits = 8 - bitsToAddCount; + final long nextByte = in.read(); + if (nextByte < 0) { + return nextByte; + } + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + long bitsToAdd = nextByte & MASKS[bitsToAddCount]; + bitsCached |= (bitsToAdd << bitsCachedSize); + overflow = (nextByte >>> bitsToAddCount) & MASKS[overflowBits]; + } else { + bitsCached <<= bitsToAddCount; + long bitsToAdd = (nextByte >>> (overflowBits)) & MASKS[bitsToAddCount]; + bitsCached |= bitsToAdd; + overflow = nextByte & MASKS[overflowBits]; + } + bitsCachedSize = count; + bitsOut = bitsCached & MASKS[count]; + bitsCached = overflow; + bitsCachedSize = overflowBits; + return bitsOut; + } + + /** + * Fills the cache up to 56 bits + * @param count + * @return return true, when EOF + * @throws IOException + */ + private boolean ensureCache(final int count) throws IOException { + while (bitsCachedSize < count && bitsCachedSize < 57) { final long nextByte = in.read(); if (nextByte < 0) { - return nextByte; + return true; } if (byteOrder == ByteOrder.LITTLE_ENDIAN) { - long bitsToAdd = nextByte & MASKS[bitsToAddCount]; - bitsCached |= (bitsToAdd << bitsCachedSize); - overflow = (nextByte >>> bitsToAddCount) & MASKS[overflowBits]; - } else { - bitsCached <<= bitsToAddCount; - long bitsToAdd = (nextByte >>> (overflowBits)) & MASKS[bitsToAddCount]; - bitsCached |= bitsToAdd; - overflow = nextByte & MASKS[overflowBits]; - } - bitsCachedSize = count; - } - - final long bitsOut; - if (overflowBits == 0) { - if (byteOrder == ByteOrder.LITTLE_ENDIAN) { - bitsOut = (bitsCached & MASKS[count]); - bitsCached >>>= count; + bitsCached |= (nextByte << bitsCachedSize); } else { - bitsOut = (bitsCached >> (bitsCachedSize - count)) & MASKS[count]; + bitsCached <<= 8; + bitsCached |= nextByte; } - bitsCachedSize -= count; - } else { - bitsOut = bitsCached & MASKS[count]; - bitsCached = overflow; - bitsCachedSize = overflowBits; + bitsCachedSize += 8; } - return bitsOut; + return false; } }