Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4837564

(bf) Please make DirectByteBuffer performance enhancements

    Details

    • Subcomponent:
    • Resolved In Build:
      b116
    • CPU:
      x86
    • OS:
      windows_2000
    • Verification:
      Not verified

      Description



      Name: rmT116609 Date: 03/25/2003


      A DESCRIPTION OF THE REQUEST :
      The most important enhancement I would like to see is removal of the page alignment.
      It would appear that every DirectByteBuffer wastes a PageSize of data (4096 bytes on my platform). It also wastes time setting this unused memory to 0. When it doesn't get returned page aligned it then creates another buffer.
      I have looked through the code and it never makes use of the page alignment.
      Instead it uses an aligned property to determine if it can get the values directly or if it needs to create them from bytes instead.
      If the intention was to have bigger allocation blocks then IMHO a better approach would have been to call allocateMemory with capacity rounded up to the nearest page size (e.g. 8000 bytes goes to 8192 bytes). Also this unused space (in this case 192) could be returned to another buffer, if that later buffer requests a buffer with capacity <= 192.

      If changes are getting made anyway, then removal of the << 0 scatterred throughout the DirectByteBuffer class might also be a good idea. I assume these were generated somehow. For int i the << 0 makes absolutely no difference for any value of i except for possibly slowing down performance.

      Also assert (pos <= lim);
      int rem = (pos <= lim ? lim - pos : 0);
      should be simplified to assert (pos <= lim);
      int rem = lim - pos;

      etc.

      Note: Fixes are getting done to DirectByteBuffer for JDK 1.4.2 for bugs 4827358 and hopefully also for the bug corresponding to review id 182986.

      JUSTIFICATION :
      I noticed incredible amounts of paging going on under Windows, so much so that the whole system just stood still. After tracing through to find the cause of it, yet again DirectByteBuffer's were the problem. The cause was that every DirectByteBuffer was wasting 4096 bytes, hence memory consumption was a lot more than it needed to be.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Performance of the direct buffer to be somewhat comparable with the heap buffer.
      Most of our direct byte buffer usage is for reading writing to channels.
      With this behaviour heap buffers do a better job than direct buffers even it situations ideally suited to direct buffers. The performance difference is from almost instantaneous, to seemingly stationary.
      On my platform, heap buffer took 0 seconds, direct buffers took 4 minutes.
      The exaggerated example is just to make the point, in actual code, direct byte buffers are only about 4000 x slower than heap buffers even though in our actual code direct buffers are meant to have the potential of being a lot faster.

      ---------- BEGIN SOURCE ----------
      import java.nio.*;

      public class Test {
        public static void main(String[] args) {
          ByteBuffer[] buffers = new ByteBuffer[100000];
          long startTime = System.currentTimeMillis();
          for (int i = 0; i < buffers.length; i++) {
            buffers[i] = ByteBuffer.allocate(1);
          }
          for (int i = 0; i < buffers.length; i++) {
            buffers[i].put((byte)0);
          }
          System.out.println("Time Taken Heap Buffer: " + (System.currentTimeMillis() - startTime) / 1000 + " seconds");

          buffers = new ByteBuffer[100000];
          System.gc();
          System.runFinalization();

          startTime = System.currentTimeMillis();
          for (int i = 0; i < buffers.length; i++) {
            buffers[i] = ByteBuffer.allocateDirect(1);
          }
          for (int i = 0; i < buffers.length; i++) {
            buffers[i].put((byte)0);
          }
          System.out.println("Time Taken Direct Buffer: " + (System.currentTimeMillis() - startTime) / 1000 + " seconds");
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Allocate your own direct buffers a lot bigger than they need to be.
      Then use slice to return buffers the actual size they need to be.
      4096 bytes will only get wasted per allocation buffer instead of per buffer this way.
      It is a little more tricky as if any of the buffer slices still exist then none of the allocation buffer can be freed.

      Alternatively use Heap Buffers instead. The performance is still faster than using direct buffers when all this paging needs to be done. Bug 4411600 is still a problem for this way as well though.
      (Review ID: 183021)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                alanb Alan Bateman
                Reporter:
                rmandalasunw Ranjith Mandala (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: