title: Why the odd performance curve differential between ByteBuffer.allocate() and ByteBuffer.allocateDirect()
body: <p>I'm working on some <code>SocketChannel</code>-to-<code>SocketChannel</code> code which will do best with a direct byte buffer--long lived and large (tens to hundreds of megabytes per connection.)  While hashing out the exact loop structure with <code>FileChannel</code>s, I ran some micro-benchmarks on <code>ByteBuffer.allocate()</code> vs. <code>ByteBuffer.allocateDirect()</code> performance.</p>
  
  <p>There was a surprise in the results that I can't really explain.  In the below graph, there is a very pronounced cliff at the 256KB and 512KB for the <code>ByteBuffer.allocate()</code> transfer implementation--the performance drops by ~50%!  There also seem sto be a smaller performance cliff for the <code>ByteBuffer.allocateDirect()</code>.  (The %-gain series helps to visualize these changes.)</p>
  
  <p><strong>Buffer Size (bytes) versus Time (MS)</strong></p>
  
  <p><img src="https://i.stack.imgur.com/NvnhU.png" alt="The Pony Gap"></p>
  
  <p><strong><em>Why the odd performance curve differential between <code>ByteBuffer.allocate()</code> and <code>ByteBuffer.allocateDirect()</code>?</em></strong>  What exactly is going on behind the curtain?</p>
  
  <p>It very well maybe hardware and OS dependent, so here are those details:</p>
  
  <ul>
  <li>MacBook Pro w/ Dual-core Core 2 CPU</li>
  <li>Intel X25M SSD drive</li>
  <li>OSX 10.6.4</li>
  </ul>
  
  <p>Source code, by request:</p>
  
  <pre><code>package ch.dietpizza.bench;
  
  import static java.lang.String.format;
  import static java.lang.System.out;
  import static java.nio.ByteBuffer.*;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.UnknownHostException;
  import java.nio.ByteBuffer;
  import java.nio.channels.Channels;
  import java.nio.channels.ReadableByteChannel;
  import java.nio.channels.WritableByteChannel;
  
  public class SocketChannelByteBufferExample {
      private static WritableByteChannel target;
      private static ReadableByteChannel source;
      private static ByteBuffer          buffer;
  
      public static void main(String[] args) throws IOException, InterruptedException {
          long timeDirect;
          long normal;
          out.println("start");
  
          for (int i = 512; i &lt;= 1024 * 1024 * 64; i *= 2) {
              buffer = allocateDirect(i);
              timeDirect = copyShortest();
  
              buffer = allocate(i);
              normal = copyShortest();
  
              out.println(format("%d, %d, %d", i, normal, timeDirect));
          }
  
          out.println("stop");
      }
  
      private static long copyShortest() throws IOException, InterruptedException {
          int result = 0;
          for (int i = 0; i &lt; 100; i++) {
              int single = copyOnce();
              result = (i == 0) ? single : Math.min(result, single);
          }
          return result;
      }
  
  
      private static int copyOnce() throws IOException, InterruptedException {
          initialize();
  
          long start = System.currentTimeMillis();
  
          while (source.read(buffer)!= -1) {    
              buffer.flip();  
              target.write(buffer);
              buffer.clear();  //pos = 0, limit = capacity
          }
  
          long time = System.currentTimeMillis() - start;
  
          rest();
  
          return (int)time;
      }   
  
  
      private static void initialize() throws UnknownHostException, IOException {
          InputStream  is = new FileInputStream(new File("/Users/stu/temp/robyn.in"));//315 MB file
          OutputStream os = new FileOutputStream(new File("/dev/null"));
  
          target = Channels.newChannel(os);
          source = Channels.newChannel(is);
      }
  
      private static void rest() throws InterruptedException {
          System.gc();
          Thread.sleep(200);      
      }
  }
  </code></pre>