You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2020/07/14 01:15:34 UTC

[incubator-iotdb] branch master updated: [IOTDB-716] add lZ4 compress method (#1448)

This is an automated email from the ASF dual-hosted git repository.

qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e628d2  [IOTDB-716] add lZ4 compress method (#1448)
7e628d2 is described below

commit 7e628d29d20d39db0473f2d8303a28510b61d0c5
Author: SilverNarcissus <15...@smail.nju.edu.cn>
AuthorDate: Tue Jul 14 09:15:23 2020 +0800

    [IOTDB-716] add lZ4 compress method (#1448)
---
 LICENSE-binary                                     |   1 +
 .../resources/conf/iotdb-engine.properties         |   2 +-
 .../iotdb/db/integration/IoTDBMultiSeriesIT.java   |   2 +
 tsfile/pom.xml                                     |   5 +
 .../apache/iotdb/tsfile/compress/ICompressor.java  |  47 ++++++++-
 .../iotdb/tsfile/compress/IUnCompressor.java       | 106 ++++++++++++++++++---
 .../file/metadata/enums/CompressionType.java       |  10 +-
 .../tsfile/read/reader/chunk/ChunkReader.java      |   5 +-
 .../apache/iotdb/tsfile/compress/CompressTest.java |  32 ++++++-
 .../compress/{SnappyTest.java => LZ4Test.java}     |  41 +++-----
 .../apache/iotdb/tsfile/compress/SnappyTest.java   |  21 ++--
 11 files changed, 214 insertions(+), 58 deletions(-)

diff --git a/LICENSE-binary b/LICENSE-binary
index 296000b..3482bc9 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -229,6 +229,7 @@ com.fasterxml.jackson.core:jackson-annotations:2.10.0
 com.fasterxml.jackson.core:jackson-core:2.10.0
 com.fasterxml.jackson.core:jackson-databind:2.10.0
 javax.inject:javax.inject:1
+net.jpountz.lz4:1.3.0
 com.github.stephenc.jcip:jcip-annotations:1.0-1
 org.eclipse.jetty:jetty-http:9.4.24.v20191120
 org.eclipse.jetty:jetty-io:9.4.24.v20191120
diff --git a/server/src/assembly/resources/conf/iotdb-engine.properties b/server/src/assembly/resources/conf/iotdb-engine.properties
index 2947d2d..eed49ae 100644
--- a/server/src/assembly/resources/conf/iotdb-engine.properties
+++ b/server/src/assembly/resources/conf/iotdb-engine.properties
@@ -460,7 +460,7 @@ time_encoder=TS_2DIFF
 value_encoder=PLAIN
 
 # Compression configuration
-# Data compression method, supports UNCOMPRESSED or SNAPPY. Default value is SNAPPY
+# Data compression method, supports UNCOMPRESSED, SNAPPY or LZ4. Default value is SNAPPY
 compressor=SNAPPY
 
 # Maximum degree of a metadataIndex node, default value is 1024
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
index e39ae5b..5a15214 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
@@ -69,6 +69,7 @@ public class IoTDBMultiSeriesIT {
     IoTDBDescriptor.getInstance().getConfig().setMemtableSizeThreshold(1024 * 1000);
     prevPartitionInterval = IoTDBDescriptor.getInstance().getConfig().getPartitionInterval();
     IoTDBDescriptor.getInstance().getConfig().setPartitionInterval(100);
+    TSFileDescriptor.getInstance().getConfig().setCompressor("LZ4");
 
     EnvironmentUtils.envSetUp();
 
@@ -84,6 +85,7 @@ public class IoTDBMultiSeriesIT {
     EnvironmentUtils.cleanEnv();
     IoTDBDescriptor.getInstance().getConfig().setPartitionInterval(prevPartitionInterval);
     IoTDBDescriptor.getInstance().getConfig().setMemtableSizeThreshold(groupSizeInByte);
+    TSFileDescriptor.getInstance().getConfig().setCompressor("SNAPPY");
   }
 
   private static void insertData()
diff --git a/tsfile/pom.xml b/tsfile/pom.xml
index ba5e1b0..3e235fa 100644
--- a/tsfile/pom.xml
+++ b/tsfile/pom.xml
@@ -53,6 +53,11 @@
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
+        <dependency>
+            <groupId>net.jpountz.lz4</groupId>
+            <artifactId>lz4</artifactId>
+            <version>1.3.0</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/ICompressor.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/ICompressor.java
index 4c94069..c70570b 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/ICompressor.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/ICompressor.java
@@ -22,11 +22,11 @@ package org.apache.iotdb.tsfile.compress;
 import java.io.IOException;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
-
-import org.xerial.snappy.Snappy;
-
+import net.jpountz.lz4.LZ4Compressor;
+import net.jpountz.lz4.LZ4Factory;
 import org.apache.iotdb.tsfile.exception.compress.CompressionTypeNotSupportedException;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.xerial.snappy.Snappy;
 
 /**
  * compress data according to type in schema.
@@ -52,6 +52,8 @@ public interface ICompressor extends Serializable {
         return new NoCompressor();
       case SNAPPY:
         return new SnappyCompressor();
+      case LZ4:
+        return new IOTDBLZ4Compressor();
       default:
         throw new CompressionTypeNotSupportedException(name.toString());
     }
@@ -140,4 +142,43 @@ public interface ICompressor extends Serializable {
       return CompressionType.SNAPPY;
     }
   }
+
+  class IOTDBLZ4Compressor implements ICompressor {
+    private LZ4Compressor compressor;
+
+    public IOTDBLZ4Compressor(){
+      super();
+      LZ4Factory factory = LZ4Factory.fastestInstance();
+      compressor = factory.fastCompressor();
+    }
+
+    @Override
+    public byte[] compress(byte[] data) throws IOException {
+      if (data == null) {
+        return new byte[0];
+      }
+      return compressor.compress(data);
+    }
+
+    @Override
+    public int compress(byte[] data, int offset, int length, byte[] compressed) throws IOException {
+      return compressor.compress(data, offset, length, compressed, 0);
+    }
+
+    @Override
+    public int compress(ByteBuffer data, ByteBuffer compressed) throws IOException {
+      compressor.compress(data, compressed);
+      return data.limit();
+    }
+
+    @Override
+    public int getMaxBytesForCompression(int uncompressedDataSize) {
+      return compressor.maxCompressedLength(uncompressedDataSize);
+    }
+
+    @Override
+    public CompressionType getType() {
+      return CompressionType.LZ4;
+    }
+  }
 }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/IUnCompressor.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/IUnCompressor.java
index 9624804..82ccc3e 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/IUnCompressor.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/compress/IUnCompressor.java
@@ -21,14 +21,15 @@ package org.apache.iotdb.tsfile.compress;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-
+import net.jpountz.lz4.LZ4Compressor;
+import net.jpountz.lz4.LZ4Factory;
+import net.jpountz.lz4.LZ4SafeDecompressor;
+import org.apache.iotdb.tsfile.exception.compress.CompressionTypeNotSupportedException;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xerial.snappy.Snappy;
 
-import org.apache.iotdb.tsfile.exception.compress.CompressionTypeNotSupportedException;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
-
 /**
  * uncompress data according to type in metadata.
  */
@@ -49,6 +50,8 @@ public interface IUnCompressor {
         return new NoUnCompressor();
       case SNAPPY:
         return new SnappyUnCompressor();
+      case LZ4:
+        return new LZ4UnCompressor();
       default:
         throw new CompressionTypeNotSupportedException(name.toString());
     }
@@ -69,15 +72,15 @@ public interface IUnCompressor {
    * @param byteArray to be uncompressed bytes
    * @return bytes after uncompressed
    */
-  public abstract byte[] uncompress(byte[] byteArray);
+  public abstract byte[] uncompress(byte[] byteArray) throws IOException;
 
   /**
    * uncompress the byte array.
    *
    * @param byteArray -to be uncompressed bytes
-   * @param offset -offset
-   * @param length -length
-   * @param output -output byte
+   * @param offset    -offset
+   * @param length    -length
+   * @param output    -output byte
    * @param outOffset -
    * @return the valid length of the output array
    */
@@ -87,7 +90,7 @@ public interface IUnCompressor {
   /**
    * if the data is large, using this function is better.
    *
-   * @param compressed MUST be DirectByteBuffer
+   * @param compressed   MUST be DirectByteBuffer
    * @param uncompressed MUST be DirectByteBuffer
    */
   int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws IOException;
@@ -112,9 +115,9 @@ public interface IUnCompressor {
     }
 
     @Override
-    public int uncompress(byte[] byteArray, int offset, int length, byte[] output, int outOffset)
-        throws IOException {
-      throw new IOException("NoUnCompressor does not support this method.");
+    public int uncompress(byte[] byteArray, int offset, int length, byte[] output, int outOffset) {
+      System.arraycopy(byteArray, offset, output, outOffset, length);
+      return length;
     }
 
     @Override
@@ -160,7 +163,6 @@ public interface IUnCompressor {
     @Override
     public int uncompress(byte[] byteArray, int offset, int length, byte[] output, int outOffset)
         throws IOException {
-      Snappy.uncompressedLength(byteArray, offset, length);
       return Snappy.uncompress(byteArray, offset, length, output, outOffset);
     }
 
@@ -184,4 +186,82 @@ public interface IUnCompressor {
       return CompressionType.SNAPPY;
     }
   }
+
+
+  class LZ4UnCompressor implements IUnCompressor {
+
+    private static final Logger logger = LoggerFactory.getLogger(LZ4Compressor.class);
+    private static final int MAX_COMPRESS_RATIO = 255;
+    private LZ4SafeDecompressor decompressor;
+
+
+    public LZ4UnCompressor() {
+      LZ4Factory factory = LZ4Factory.fastestInstance();
+      decompressor = factory.safeDecompressor();
+    }
+
+    @Override
+    public int getUncompressedLength(byte[] array, int offset, int length) throws IOException {
+      throw new UnsupportedOperationException("unsupported get uncompress length");
+    }
+
+    @Override
+    public int getUncompressedLength(ByteBuffer buffer) throws IOException {
+      throw new UnsupportedOperationException("unsupported get uncompress length");
+    }
+
+    /**
+     * We don't recommend using this method because we have to allocate MAX_COMPRESS_RATIO *
+     * compressedSize to ensure uncompress safety, you can use other method if you know the
+     * uncompressed size
+     */
+    @Override
+    public byte[] uncompress(byte[] bytes) throws IOException {
+      if (bytes == null) {
+        return new byte[0];
+      }
+
+      try {
+        return decompressor.decompress(bytes, MAX_COMPRESS_RATIO * bytes.length);
+      } catch (RuntimeException e) {
+        logger.error(
+            "tsfile-compression LZ4UnCompressor: errors occurs when uncompress input byte", e);
+        throw new IOException(e);
+      }
+    }
+
+    @Override
+    public int uncompress(byte[] byteArray, int offset, int length, byte[] output, int outOffset)
+        throws IOException {
+      try {
+        return decompressor.decompress(byteArray, offset, length, output, offset);
+      }
+      catch (RuntimeException e){
+        logger.error(
+            "tsfile-compression LZ4UnCompressor: errors occurs when uncompress input byte", e);
+        throw new IOException(e);
+      }
+    }
+
+    @Override
+    public int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws IOException {
+      if (compressed == null || !compressed.hasRemaining()) {
+        return 0;
+      }
+
+      try {
+        decompressor.decompress(compressed, uncompressed);
+        return compressed.limit();
+      } catch (RuntimeException e) {
+        logger.error(
+            "tsfile-compression LZ4UnCompressor: errors occurs when uncompress input byte", e);
+        throw new IOException(e);
+      }
+    }
+
+    @Override
+    public CompressionType getCodecName() {
+      return CompressionType.LZ4;
+    }
+  }
 }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/enums/CompressionType.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/enums/CompressionType.java
index d6a09b2..43a0eaa 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/enums/CompressionType.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/enums/CompressionType.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.tsfile.file.metadata.enums;
 import org.apache.iotdb.tsfile.exception.compress.CompressionTypeNotSupportedException;
 
 public enum CompressionType {
-  UNCOMPRESSED, SNAPPY, GZIP, LZO, SDT, PAA, PLA;
+  UNCOMPRESSED, SNAPPY, GZIP, LZO, SDT, PAA, PLA, LZ4;
 
   /**
    * deserialize short number.
@@ -45,6 +45,8 @@ public enum CompressionType {
         return PAA;
       case 6:
         return PLA;
+      case 7:
+        return LZ4;
       default:
         return UNCOMPRESSED;
     }
@@ -79,6 +81,8 @@ public enum CompressionType {
         return PAA;
       case "PLA":
         return PLA;
+      case "LZ4":
+        return LZ4;
       default:
         throw new CompressionTypeNotSupportedException(name);
     }
@@ -105,6 +109,8 @@ public enum CompressionType {
         return 5;
       case PLA:
         return 6;
+      case LZ4:
+        return 7;
       default:
         return 0;
     }
@@ -131,6 +137,8 @@ public enum CompressionType {
         return ".paa";
       case PLA:
         return ".pla";
+      case LZ4:
+        return ".lz4";
       default:
         return "";
     }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/chunk/ChunkReader.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/chunk/ChunkReader.java
index aa5d7ff..57549a4 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/chunk/ChunkReader.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/chunk/ChunkReader.java
@@ -159,7 +159,10 @@ public class ChunkReader implements IChunkReader {
     chunkDataBuffer.get(compressedPageBody);
     Decoder valueDecoder = Decoder
             .getDecoderByType(chunkHeader.getEncodingType(), chunkHeader.getDataType());
-    ByteBuffer pageData = ByteBuffer.wrap(unCompressor.uncompress(compressedPageBody));
+    byte[] uncompressedPageData = new byte[pageHeader.getUncompressedSize()];
+    unCompressor.uncompress(compressedPageBody,0, compressedPageBodyLength,
+        uncompressedPageData, 0);
+    ByteBuffer pageData = ByteBuffer.wrap(uncompressedPageData);
     PageReader reader = new PageReader(pageHeader, pageData, chunkHeader.getDataType(),
         valueDecoder, timeDecoder, filter);
     reader.setDeleteIntervalList(deleteIntervalList);
diff --git a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/CompressTest.java b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/CompressTest.java
index bc776b3..0834d75 100644
--- a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/CompressTest.java
+++ b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/CompressTest.java
@@ -23,16 +23,12 @@ import static org.junit.Assert.assertEquals;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
-
+import org.apache.iotdb.tsfile.utils.PublicBAOS;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.xerial.snappy.Snappy;
 
-import org.apache.iotdb.tsfile.compress.ICompressor;
-import org.apache.iotdb.tsfile.compress.IUnCompressor;
-import org.apache.iotdb.tsfile.utils.PublicBAOS;
-
 public class CompressTest {
 
   private final String inputString = "Hello snappy-java! Snappy-java is a JNI-based wrapper of "
@@ -81,4 +77,30 @@ public class CompressTest {
     assertEquals(inputString, result);
   }
 
+
+  @Test
+  public void lz4CompressorTest1() throws IOException {
+    PublicBAOS out = new PublicBAOS();
+    out.write(inputString.getBytes(StandardCharsets.UTF_8));
+    ICompressor compressor = new ICompressor.IOTDBLZ4Compressor();
+    IUnCompressor unCompressor = new IUnCompressor.LZ4UnCompressor();
+    byte[] compressed = compressor.compress(out.getBuf());
+    byte[] uncompressed = unCompressor.uncompress(compressed);
+    String result = new String(uncompressed, StandardCharsets.UTF_8);
+    assertEquals(inputString, result);
+  }
+
+  @Test
+  public void lz4CompressorTest2() throws IOException {
+    PublicBAOS out = new PublicBAOS();
+    out.write(inputString.getBytes(StandardCharsets.UTF_8));
+    ICompressor compressor = new ICompressor.IOTDBLZ4Compressor();
+    IUnCompressor unCompressor = new IUnCompressor.LZ4UnCompressor();
+    byte[] compressed = new byte[compressor.getMaxBytesForCompression(out.size())];
+    int size = compressor.compress(out.getBuf(), 0, out.size(), compressed);
+    byte[] bytes = Arrays.copyOfRange(compressed, 0, size);
+    byte[] uncompressed = unCompressor.uncompress(bytes);
+    String result = new String(uncompressed, StandardCharsets.UTF_8);
+    assertEquals(inputString, result);
+  }
 }
diff --git a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/LZ4Test.java
similarity index 58%
copy from tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java
copy to tsfile/src/test/java/org/apache/iotdb/tsfile/compress/LZ4Test.java
index 8f58a6d..250a2df 100644
--- a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java
+++ b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/LZ4Test.java
@@ -19,18 +19,16 @@
 package org.apache.iotdb.tsfile.compress;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ThreadLocalRandom;
-
+import org.apache.iotdb.tsfile.compress.ICompressor.IOTDBLZ4Compressor;
+import org.apache.iotdb.tsfile.compress.IUnCompressor.LZ4UnCompressor;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.xerial.snappy.Snappy;
-
-import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
-public class SnappyTest {
+public class LZ4Test {
 
   private String randomString(int length) {
     StringBuilder builder = new StringBuilder(length);
@@ -50,33 +48,22 @@ public class SnappyTest {
 
   @Test
   public void testBytes() throws IOException {
-    String input = randomString(50000);
+    String input = randomString(2000000);
     byte[] uncom = input.getBytes(StandardCharsets.UTF_8);
     long time = System.currentTimeMillis();
-    byte[] compressed = Snappy.compress(uncom);
-    System.out.println("compression time cost:" + (System.currentTimeMillis() - time));
-    time = System.currentTimeMillis();
-    byte[] uncompressed = Snappy.uncompress(compressed);
-    System.out.println("decompression time cost:" + (System.currentTimeMillis() - time));
-  }
+    ICompressor compressor = new IOTDBLZ4Compressor();
 
-  @Test
-  public void testByteBuffer() throws IOException {
-    String input = randomString(5000);
-    ByteBuffer source = ByteBuffer.allocateDirect(input.getBytes().length);
-    source.put(input.getBytes());
-    source.flip();
-
-    long time = System.currentTimeMillis();
-    ByteBuffer compressed = ByteBuffer.allocateDirect(Snappy.maxCompressedLength(source.remaining()));
-    Snappy.compress(source, compressed);
+    byte[] compressed = compressor.compress(uncom);
     System.out.println("compression time cost:" + (System.currentTimeMillis() - time));
-    Snappy.uncompressedLength(compressed);
     time = System.currentTimeMillis();
-    ByteBuffer uncompressedByteBuffer = ByteBuffer.allocateDirect(Snappy.uncompressedLength(compressed) + 1);
-    Snappy.uncompress(compressed, uncompressedByteBuffer);
+    System.out.println("ratio: " + (double) compressed.length / uncom.length);
+
+    IUnCompressor unCompressor = new LZ4UnCompressor();
+    byte[] uncompressed = new byte[uncom.length];
+    unCompressor.uncompress(compressed, 0, compressed.length, uncompressed, 0);
     System.out.println("decompression time cost:" + (System.currentTimeMillis() - time));
-    assert input.equals(ReadWriteIOUtils.readStringFromDirectByteBuffer(uncompressedByteBuffer));
+
+    Assert.assertArrayEquals(uncom, uncompressed);
   }
 
 }
diff --git a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java
index 8f58a6d..ad0e3a4 100644
--- a/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java
+++ b/tsfile/src/test/java/org/apache/iotdb/tsfile/compress/SnappyTest.java
@@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ThreadLocalRandom;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.xerial.snappy.Snappy;
@@ -50,14 +51,18 @@ public class SnappyTest {
 
   @Test
   public void testBytes() throws IOException {
-    String input = randomString(50000);
+    int n = 500000;
+    String input = randomString(n);
     byte[] uncom = input.getBytes(StandardCharsets.UTF_8);
-    long time = System.currentTimeMillis();
+    long time = System.nanoTime();
     byte[] compressed = Snappy.compress(uncom);
-    System.out.println("compression time cost:" + (System.currentTimeMillis() - time));
-    time = System.currentTimeMillis();
+    System.out.println("compression time cost:" + ((System.nanoTime() - time)) / 1000 / 1000);
+    System.out.println("ratio: " + (double) compressed.length / uncom.length);
+    time = System.nanoTime();
     byte[] uncompressed = Snappy.uncompress(compressed);
-    System.out.println("decompression time cost:" + (System.currentTimeMillis() - time));
+    System.out.println("decompression time cost:" + ((System.nanoTime() - time)) / 1000 / 1000);
+
+    Assert.assertArrayEquals(uncom, uncompressed);
   }
 
   @Test
@@ -68,12 +73,14 @@ public class SnappyTest {
     source.flip();
 
     long time = System.currentTimeMillis();
-    ByteBuffer compressed = ByteBuffer.allocateDirect(Snappy.maxCompressedLength(source.remaining()));
+    ByteBuffer compressed = ByteBuffer
+        .allocateDirect(Snappy.maxCompressedLength(source.remaining()));
     Snappy.compress(source, compressed);
     System.out.println("compression time cost:" + (System.currentTimeMillis() - time));
     Snappy.uncompressedLength(compressed);
     time = System.currentTimeMillis();
-    ByteBuffer uncompressedByteBuffer = ByteBuffer.allocateDirect(Snappy.uncompressedLength(compressed) + 1);
+    ByteBuffer uncompressedByteBuffer = ByteBuffer
+        .allocateDirect(Snappy.uncompressedLength(compressed) + 1);
     Snappy.uncompress(compressed, uncompressedByteBuffer);
     System.out.println("decompression time cost:" + (System.currentTimeMillis() - time));
     assert input.equals(ReadWriteIOUtils.readStringFromDirectByteBuffer(uncompressedByteBuffer));