title: When to use Array, Buffer or direct Buffer
body: <h1>Question</h1>
  
  <p>While writing a Matrix class for use with OpenGL libraries, I came across the question of whether to use Java arrays or a Buffer strategy to store the data (JOGL offers direct-buffer copy for Matrix operations). To analyze this, I wrote a small performance test program that compares the relative speeds of loop and bulk operations on Arrays vs Buffers vs direct Buffers.</p>
  
  <p>I'd like to share my results with you here (as I find them rather interesting). Please feel free to comment and/or point out any mistakes.<br>
  The code can be viewed at <a href="http://pastebin.com/is7UaiMV" rel="noreferrer">pastebin.com/is7UaiMV</a>.</p>
  
  <h1>Notes</h1>
  
  <ul>
  <li><p>Loop-read array is implemented as <em>A[i] = B[i]</em> as otherwise the JIT optimizer will completely remove that code. Actual <em>var = A[i]</em> seems to be pretty much the same.</p></li>
  <li><p>In the sample result for array size of 10,000 it is very likely that the JIT optimizer has replaced the looped array access with a System.arraycopy like implementation.</p></li>
  <li><p>There is no bulk-get buffer->buffer as Java implements <em>A.get(B)</em> as <em>B.put(A)</em>, therefore the results would be the same as the bulk-put results.</p></li>
  </ul>
  
  <h1>Conclusion</h1>
  
  <p>Under almost all situations it is strongly recommended to use the Java internal Arrays. Not only is the put/get speed massively faster, the JIT is as well able to perform much better optimizations on the final code.</p>
  
  <p>Buffers should <strong>only</strong> be used if <strong>both</strong> the following applies:</p>
  
  <ul>
  <li>You need to process <strong>large amounts</strong> of data.</li>
  <li>That data is mostly or always <strong>bulk-processed</strong>.</li>
  </ul>
  
  <p>Note that a backened-buffer has a Java Array backening the content of the buffer. It is recommended to do operations on this back-buffer instead of looping put/get.</p>
  
  <p>Direct buffers should <strong>only</strong> be used if you worry about <strong>memory usage</strong> and never access the underlying data. They are slightly slower than non-direct buffers, much slower if the underlying data is accessed, but use less memory. In addition there is an extra overhead when converting non-byte data (like float-arrays) into bytes when using a direct buffer.</p>
  
  <p>For more details see here:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/3651737/why-the-odd-performance-curve-differential-between-bytebuffer-allocate-and-byt/11004231#11004231" title="Why only direct Byte buffers are useful">Why only ByteBuffers are useful when using direct buffers</a></li>
  <li><a href="https://stackoverflow.com/questions/5670862/bytebuffer-allocate-vs-bytebuffer-allocatedirect/5671880#5671880" title="Internal overhead of NIO">Internal overhead on NIO and what slows buffers down</a></li>
  </ul>
  
  <h1>Sample results</h1>
  
  <p><em>Note: Percentage is only for ease of reading and has no real meaning.</em></p>
  
  <h3>Using arrays of size 16 with 10,000,000 iterations...</h3>
  
  <pre><code>-- Array tests: -----------------------------------------
  
  Loop-write array:           87.29 ms  11,52%
  Arrays.fill:                64.51 ms   8,51%
  Loop-read array:            42.11 ms   5,56%
  System.arraycopy:           47.25 ms   6,23%
  
  -- Buffer tests: ----------------------------------------
  
  Loop-put buffer:           603.71 ms  79,65%
  Index-put buffer:          536.05 ms  70,72%
  Bulk-put array-&gt;buffer:    105.43 ms  13,91%
  Bulk-put buffer-&gt;buffer:    99.09 ms  13,07%
  
  Bulk-put bufferD-&gt;buffer:   80.38 ms  10,60%
  Loop-get buffer:           505.77 ms  66,73%
  Index-get buffer:          562.84 ms  74,26%
  Bulk-get buffer-&gt;array:    137.86 ms  18,19%
  
  -- Direct buffer tests: ---------------------------------
  
  Loop-put bufferD:          570.69 ms  75,29%
  Index-put bufferD:         562.76 ms  74,25%
  Bulk-put array-&gt;bufferD:   712.16 ms  93,96%
  Bulk-put buffer-&gt;bufferD:   83.53 ms  11,02%
  
  Bulk-put bufferD-&gt;bufferD: 118.00 ms  15,57%
  Loop-get bufferD:          528.62 ms  69,74%
  Index-get bufferD:         560.36 ms  73,93%
  Bulk-get bufferD-&gt;array:   757.95 ms 100,00%
  </code></pre>
  
  <h3>Using arrays of size 1,000 with 100,000 iterations...</h3>
  
  <pre><code>-- Array tests: -----------------------------------------
  
  Loop-write array:           22.10 ms   6,21%
  Arrays.fill:                10.37 ms   2,91%
  Loop-read array:            81.12 ms  22,79%
  System.arraycopy:           10.59 ms   2,97%
  
  -- Buffer tests: ----------------------------------------
  
  Loop-put buffer:           355.98 ms 100,00%
  Index-put buffer:          353.80 ms  99,39%
  Bulk-put array-&gt;buffer:     16.33 ms   4,59%
  Bulk-put buffer-&gt;buffer:     5.40 ms   1,52%
  
  Bulk-put bufferD-&gt;buffer:    4.95 ms   1,39%
  Loop-get buffer:           299.95 ms  84,26%
  Index-get buffer:          343.05 ms  96,37%
  Bulk-get buffer-&gt;array:     15.94 ms   4,48%
  
  -- Direct buffer tests: ---------------------------------
  
  Loop-put bufferD:          355.11 ms  99,75%
  Index-put bufferD:         348.63 ms  97,93%
  Bulk-put array-&gt;bufferD:   190.86 ms  53,61%
  Bulk-put buffer-&gt;bufferD:    5.60 ms   1,57%
  
  Bulk-put bufferD-&gt;bufferD:   7.73 ms   2,17%
  Loop-get bufferD:          344.10 ms  96,66%
  Index-get bufferD:         333.03 ms  93,55%
  Bulk-get bufferD-&gt;array:   190.12 ms  53,41%
  </code></pre>
  
  <h3>Using arrays of size 10,000 with 100,000 iterations...</h3>
  
  <pre><code>-- Array tests: -----------------------------------------
  
  Loop-write array:          156.02 ms   4,37%
  Arrays.fill:               109.06 ms   3,06%
  Loop-read array:           300.45 ms   8,42%
  System.arraycopy:          147.36 ms   4,13%
  
  -- Buffer tests: ----------------------------------------
  
  Loop-put buffer:          3385.94 ms  94,89%
  Index-put buffer:         3568.43 ms 100,00%
  Bulk-put array-&gt;buffer:    159.40 ms   4,47%
  Bulk-put buffer-&gt;buffer:     5.31 ms   0,15%
  
  Bulk-put bufferD-&gt;buffer:    6.61 ms   0,19%
  Loop-get buffer:          2907.21 ms  81,47%
  Index-get buffer:         3413.56 ms  95,66%
  Bulk-get buffer-&gt;array:    177.31 ms   4,97%
  
  -- Direct buffer tests: ---------------------------------
  
  Loop-put bufferD:         3319.25 ms  93,02%
  Index-put bufferD:        3538.16 ms  99,15%
  Bulk-put array-&gt;bufferD:  1849.45 ms  51,83%
  Bulk-put buffer-&gt;bufferD:    5.60 ms   0,16%
  
  Bulk-put bufferD-&gt;bufferD:   7.63 ms   0,21%
  Loop-get bufferD:         3227.26 ms  90,44%
  Index-get bufferD:        3413.94 ms  95,67%
  Bulk-get bufferD-&gt;array:  1848.24 ms  51,79%
  </code></pre>