diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index b65858a0e7..010d20066a 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -1708,7 +1708,20 @@ public class DataHelper { /** */ public static final int MAX_UNCOMPRESSED = 40*1024; + /** + * Appx. 30% slower, 2.5% smaller than MEDIUM_COMPRESSION + */ public static final int MAX_COMPRESSION = Deflater.BEST_COMPRESSION; + /** + * Appx. 15% slower, 1.5% smaller than MEDIUM_COMPRESSION + * @since 0.9.47 + */ + public static final int HIGH_COMPRESSION = 5; + /** + * New default as of 0.9.47 + * @since 0.9.47 + */ + public static final int MEDIUM_COMPRESSION = 3; public static final int NO_COMPRESSION = Deflater.NO_COMPRESSION; /** @@ -1720,6 +1733,10 @@ public class DataHelper { * for a zero-length input. As of 0.9.29, output is valid for * a zero-length input also. * + * As of 0.9.47, this uses a level of MEDIUM_COMPRESSION, + * which is a good space/speed tradeoff. + * Prior to that, it used MAX_COMPRESSION. + * * @throws IllegalArgumentException if input size is over 40KB * @throws IllegalStateException on compression failure, as of 0.9.29 * @return null if orig is null @@ -1737,12 +1754,16 @@ public class DataHelper { * for a zero-length input. As of 0.9.29, output is valid for * a zero-length input also. * + * As of 0.9.47, this uses a level of MEDIUM_COMPRESSION, + * which is a good space/speed tradeoff. + * Prior to that, it used MAX_COMPRESSION. + * * @throws IllegalArgumentException if size is over 40KB * @throws IllegalStateException on compression failure, as of 0.9.29 * @return null if orig is null */ public static byte[] compress(byte orig[], int offset, int size) { - return compress(orig, offset, size, MAX_COMPRESSION); + return compress(orig, offset, size, MEDIUM_COMPRESSION); } /** @@ -1850,6 +1871,10 @@ public class DataHelper { */ public static byte[] decompress(byte orig[], int offset, int length) throws IOException { if (orig == null) return orig; + if (length < 23) + throw new IOException("length"); + if (length < 65559 && orig[offset + 10] == 0x01) + return zeroDecompress(orig, offset, length); if (offset + length > orig.length) throw new IOException("Bad params arrlen " + orig.length + " off " + offset + " len " + length); @@ -1881,6 +1906,53 @@ public class DataHelper { } } + /** + * Fast NO_COMPRESSION. + * ~30x faster for typ. lengths, ~20x faster for 4 KB or more. + * + * Ref: RFC 1951, RFC 1952, ResettableGzipOutputStream + * + * @param in in[off + 10] MUST BE VALIDATED == 1 before calling this. + * @param len 65558 max + * @return 23 bytes shorter + * @throws IOException on all errors + * @since 0.9.47 + */ + private static byte[] zeroDecompress(byte[] in, int off, int len) throws IOException { + if (len > 65535 + 23) + throw new IOException("length"); + try { + final int olen = len - 23; + if (in[off++] != 0x1F || + in[off++] != (byte) 0x8B || + in[off] != 0x08) + throw new IOException("header"); + off += 8; + if (in[off++] != 0x01 || + fromLongLE(in, off, 2) != olen) + throw new IOException("header"); + off += 2; + if (in[off] != (byte) ~ in[off - 2] || + in[off + 1] != (byte) ~ in[off - 1]) + throw new IOException("header"); + off += 2; + final int trailer = off + olen; + if (fromLongLE(in, trailer + 4, 4) != olen) + throw new IOException("trailer"); + CRC32 crc = new CRC32(); + crc.update(in, off, olen); + long val = crc.getValue(); + if (val != fromLongLE(in, trailer, 4)) + throw new IOException("CRC"); + final byte[] rv = new byte[olen]; + System.arraycopy(in, off, rv, 0, olen); + return rv; + } catch (ArrayIndexOutOfBoundsException aioobe) { + throw new IOException(aioobe); + } + } + + /** * Same as orig.getBytes("UTF-8") but throws an unchecked RuntimeException * instead of an UnsupportedEncodingException if no UTF-8, for ease of use. diff --git a/history.txt b/history.txt index 97b829a07a..464a50dd37 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2020-05-27 zzz + * Util: Faster gzip + * 2020-05-25 0.9.46 released 2020-05-23 zzz diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index a411b00998..87e5bffca0 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 0; + public final static long BUILD = 1; /** for example "-test" */ public final static String EXTRA = "";