content: /*
   * Copyright (C) 2010-2101 Alibaba Group Holding Limited.
   *
   * Licensed 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 com.alibaba.otter.shared.common.utils;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.lang.reflect.Method;
  import java.nio.ByteBuffer;
  import java.nio.MappedByteBuffer;
  import java.nio.channels.FileChannel;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  
  import org.apache.commons.io.IOUtils;
  
  /**
   * 测试下nio的一些操作方法性能
   * 
   * <pre>
   * jvm args : 
   * -server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=196m -Xss256k -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedOops
   * 
   * result :
   * 500Mb : 
   * copyTest cost : 12148 , 15924
   * channel cost : 14423 , 13847 
   * mapped cost : 7857 , 7883
   * sendfile cost : 5728 , 9352 
   * 
   * 1GB : 
   * copyTest cost : 32409 , 33557
   * channel cost : 32856 , 33305
   * mapped cost : 55789 , 52108
   * sendfile cost : 28179 , 30279
   * </pre>
   * 
   * @author jianghang 2011-10-10 下午03:31:17
   * @version 4.0.0
   */
  public class NioUtilsPerformance {
  
      public static void main(String args[]) throws Exception {
          long start = System.currentTimeMillis();
          long end = -1;
  
          copyTest(new File("/tmp/source.tar.gz"), new File("/tmp/target-copy.tar.gz"));
          end = System.currentTimeMillis();
          System.out.printf("%s cost : %d \n", "copyTest", end - start);
          start = end;
  
          channelTest(new File("/tmp/source.tar.gz"), new File("/tmp/target-channel.tar.gz"));
          end = System.currentTimeMillis();
          System.out.printf("%s cost : %d \n", "channel", end - start);
          start = end;
  
          mappedTest(new File("/tmp/source.tar.gz"), new File("/tmp/target-mapped.tar.gz"));
          end = System.currentTimeMillis();
          System.out.printf("%s cost : %d \n", "mapped", end - start);
          start = end;
  
          sendFileTest(new File("/tmp/source.tar.gz"), new File("/tmp/target-sendile.tar.gz"));
          end = System.currentTimeMillis();
          System.out.printf("%s cost : %d \n", "sendfile", end - start);
      }
  
      public static void copyTest(File source, File target) throws Exception {
          FileInputStream fis = null;
          FileOutputStream fos = null;
          try {
              fis = new FileInputStream(source);
              fos = new FileOutputStream(target);
              target.createNewFile();
  
              byte[] bytes = new byte[16 * 1024];
              int n = -1;
              while ((n = fis.read(bytes, 0, bytes.length)) > 0) {
                  fos.write(bytes, 0, n);
              }
  
              fos.flush();
          } finally {
              IOUtils.closeQuietly(fis);
              IOUtils.closeQuietly(fos);
          }
      }
  
      public static void channelTest(File source, File target) throws Exception {
          FileInputStream fis = null;
          FileOutputStream fos = null;
          try {
              fis = new FileInputStream(source);
              fos = new FileOutputStream(target);
              FileChannel sChannel = fis.getChannel();
              FileChannel tChannel = fos.getChannel();
  
              target.createNewFile();
  
              ByteBuffer buffer = ByteBuffer.allocate(16 * 1024);
              while (sChannel.read(buffer) > 0) {
                  buffer.flip();
                  tChannel.write(buffer);
                  buffer.clear();
              }
  
              tChannel.close();
              sChannel.close();
          } finally {
              IOUtils.closeQuietly(fis);
              IOUtils.closeQuietly(fos);
          }
      }
  
      public static void mappedTest(File source, File target) throws Exception {
          FileInputStream fis = null;
          FileOutputStream fos = null;
          MappedByteBuffer mapbuffer = null;
  
          try {
              long fileSize = source.length();
              final byte[] outputData = new byte[(int) fileSize];
              fis = new FileInputStream(source);
              fos = new FileOutputStream(target);
              FileChannel sChannel = fis.getChannel();
  
              target.createNewFile();
  
              mapbuffer = sChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
              for (int i = 0; i < fileSize; i++) {
                  outputData[i] = mapbuffer.get();
              }
  
              mapbuffer.clear();
              fos.write(outputData);
              fos.flush();
          } finally {
              IOUtils.closeQuietly(fis);
              IOUtils.closeQuietly(fos);
  
              if (mapbuffer == null) {
                  return;
              }
  
              final Object buffer = mapbuffer;
  
              AccessController.doPrivileged(new PrivilegedAction() {
  
                  public Object run() {
                      try {
                          Method clean = buffer.getClass().getMethod("cleaner", new Class[0]);
  
                          if (clean == null) {
                              return null;
                          }
                          clean.setAccessible(true);
                          sun.misc.Cleaner cleaner = (sun.misc.Cleaner) clean.invoke(buffer, new Object[0]);
                          cleaner.clean();
                      } catch (Throwable ex) {
                      }
  
                      return null;
                  }
              });
          }
      }
  
      public static void sendFileTest(File source, File target) throws Exception {
          FileInputStream fis = null;
          FileOutputStream fos = null;
          try {
              fis = new FileInputStream(source);
              fos = new FileOutputStream(target);
              FileChannel sChannel = fis.getChannel();
              FileChannel tChannel = fos.getChannel();
              target.createNewFile();
              sChannel.transferTo(0, source.length(), tChannel);
              tChannel.close();
              sChannel.close();
          } finally {
              IOUtils.closeQuietly(fis);
              IOUtils.closeQuietly(fos);
          }
      }
  }
  