title: Compression / Decompression of Strings using the deflater
body: <p>I want to compress/decompress and serialize/deserialize String content. I'm using the following two static functions.</p>
  
  <pre><code>/**
   * Compress data based on the {@link Deflater}.
   * 
   * @param pToCompress
   *            input byte-array
   * @return compressed byte-array
   * @throws NullPointerException
   *             if {@code pToCompress} is {@code null}
   */
  public static byte[] compress(@Nonnull final byte[] pToCompress) {
      checkNotNull(pToCompress);
  
      // Compressed result.
      byte[] compressed = new byte[] {};
  
      // Create the compressor.
      final Deflater compressor = new Deflater();
      compressor.setLevel(Deflater.BEST_SPEED);
  
      // Give the compressor the data to compress.
      compressor.setInput(pToCompress);
      compressor.finish();
  
      /*
       * Create an expandable byte array to hold the compressed data.
       * You cannot use an array that's the same size as the orginal because
       * there is no guarantee that the compressed data will be smaller than
       * the uncompressed data.
       */
      try (ByteArrayOutputStream bos = new ByteArrayOutputStream(pToCompress.length)) {
          // Compress the data.
          final byte[] buf = new byte[1024];
          while (!compressor.finished()) {
              final int count = compressor.deflate(buf);
              bos.write(buf, 0, count);
          }
  
          // Get the compressed data.
          compressed = bos.toByteArray();
      } catch (final IOException e) {
          LOGWRAPPER.error(e.getMessage(), e);
          throw new RuntimeException(e);
      }
  
  
      return compressed;
  }
  
  /**
   * Decompress data based on the {@link Inflater}.
   * 
   * @param pCompressed
   *            input string
   * @return compressed byte-array
   * @throws NullPointerException
   *             if {@code pCompressed} is {@code null}
   */
  public static byte[] decompress(@Nonnull final byte[] pCompressed) {
      checkNotNull(pCompressed);
  
      // Create the decompressor and give it the data to compress.
      final Inflater decompressor = new Inflater();
      decompressor.setInput(pCompressed);
  
      byte[] decompressed = new byte[] {};
  
      // Create an expandable byte array to hold the decompressed data.
      try (final ByteArrayOutputStream bos = new ByteArrayOutputStream(pCompressed.length)) {
          // Decompress the data.
          final byte[] buf = new byte[1024];
          while (!decompressor.finished()) {
              try {
                  final int count = decompressor.inflate(buf);
                  bos.write(buf, 0, count);
              } catch (final DataFormatException e) {
                  LOGWRAPPER.error(e.getMessage(), e);
                  throw new RuntimeException(e);
              }
          }
          // Get the decompressed data.
          decompressed = bos.toByteArray();
      } catch (final IOException e) {
          LOGWRAPPER.error(e.getMessage(), e);
      }
  
      return decompressed;
  }
  </code></pre>
  
  <p>Yet, compared to non-compressed values it's orders of magnitudes slower even if I'm caching the decompressed-result and the values are only decompressed if the content is really needed.</p>
  
  <p>That is, it's used for a DOM-like persistable tree-structure and XPath-queries which force the decompression of the String-values are about 50 times if not even more slower (not really benchmarked, just executed unit tests). My laptop even freezes after some unit tests (everytime, checked it about 5-times), because Eclipse isn't responding anymore due to heavy disk I/O and what not. I've even set the compression level to <code>Deflater.BEST_SPEED</code>, whereas other compression levels might be better, maybe I'm providing a configuration option parameter which can be set for <code>resources</code>. Maybe I've messed something up as I haven't used the deflater before. I'm even only compressing content where the String lenght is > 10.</p>
  
  <p>Edit: After considering to extract the Deflater instantiation to a static field it seems creating an instance of deflater and inflater is <em>very</em> costly as the performance bottleneck is gone and perhaps without microbenchmarks or the like I can't see any performance loss :-) I'm just resetting the deflater/inflater before using a new input.</p>