content: /*
   *
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
   */
  package org.apache.cassandra.io.compress;
  
  import org.apache.cassandra.io.util.FileInputStreamPlus;
  
  import java.io.IOException;
  import java.nio.ByteBuffer;
  import java.util.Collections;
  import java.util.concurrent.ThreadLocalRandom;
  
  import static org.apache.cassandra.utils.Clock.Global.nanoTime;
  
  public class CompressorPerformance
  {
  
      public static void testPerformances() throws IOException
      {
          for (ICompressor compressor: new ICompressor[] {
                  SnappyCompressor.instance,  // warm up
                  DeflateCompressor.instance,
                  LZ4Compressor.create(Collections.emptyMap()),
                  SnappyCompressor.instance,
                  ZstdCompressor.getOrCreate(ZstdCompressor.FAST_COMPRESSION_LEVEL),
                  ZstdCompressor.getOrCreate(ZstdCompressor.DEFAULT_COMPRESSION_LEVEL)
          })
          {
              for (BufferType in: BufferType.values())
              {
                  if (compressor.supports(in))
                  {
                      for (BufferType out: BufferType.values())
                      {
                          if (compressor.supports(out))
                          {
                              for (int i=0; i<10; ++i)
                                  testPerformance(compressor, in, out);
                              System.out.println();
                          }
                      }
                  }
              }
          }
      }
  
      static ByteBuffer dataSource;
      static int bufLen;
  
      private static void testPerformance(ICompressor compressor, BufferType in, BufferType out) throws IOException
      {
          int len = dataSource.capacity();
          int bufLen = compressor.initialCompressedBufferLength(len);
          ByteBuffer input = in.allocate(bufLen);
          ByteBuffer output = out.allocate(bufLen);
  
          int checksum = 0;
          int count = 100;
  
          long time = nanoTime();
          long uncompressedBytes = 0;
          long compressedBytes = 0;
          for (int i=0; i<count; ++i)
          {
              output.clear();
              compressor.compress(dataSource, output);
              uncompressedBytes += dataSource.limit();
              compressedBytes += output.position();
  
              // Make sure not optimized away.
              checksum += output.get(ThreadLocalRandom.current().nextInt(output.position()));
              dataSource.rewind();
          }
          long timec = nanoTime() - time;
          output.flip();
          input.put(output);
          input.flip();
  
          time = nanoTime();
          for (int i=0; i<count; ++i)
          {
              output.clear();
              compressor.uncompress(input, output);
              // Make sure not optimized away.
              checksum += output.get(ThreadLocalRandom.current().nextInt(output.position()));
              input.rewind();
          }
          long timed = nanoTime() - time;
          System.out.format("Compressor %s %s->%s compress %.3f ns/b %.3f mb/s uncompress %.3f ns/b %.3f mb/s ratio %.2f:1.%s\n",
                            compressor.getClass().getSimpleName(),
                            in,
                            out,
                            1.0 * timec / (count * len),
                            Math.scalb(1.0e9, -20) * count * len / timec,
                            1.0 * timed / (count * len),
                            Math.scalb(1.0e9, -20) * count * len / timed,
                            ((double) uncompressedBytes) / ((double) compressedBytes),
                            checksum == 0 ? " " : "");
      }
  
      public static void main(String[] args) throws IOException
      {
          try (FileInputStreamPlus fis = new FileInputStreamPlus("CHANGES.txt"))
          {
              int len = (int)fis.getChannel().size();
              dataSource = ByteBuffer.allocateDirect(len);
              while (dataSource.hasRemaining()) {
                  fis.getChannel().read(dataSource);
              }
              dataSource.flip();
          }
          testPerformances();
      }
  }
  