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

(bf) Improve performance of ByteBuffer.putLong()

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.2
    • core-libs
    • x86
    • windows_xp

      Name: jl125535 Date: 09/01/2004


      A DESCRIPTION OF THE REQUEST :
      Modify the HOTSPOT compiler to recognize ByteBuffer.putLong and generate optimized code that is equivalent to a series of hand coded assignments with shifts.

      ByteBuffer.putLong executes 25% to 30% slower than corresponding shift operations:

      long now = System.currentTimeMillis();
      ByteBuffer bb = ByteBuffer.allocate(8);
      bb.putLong(0, now); // is about 30% slower than the following

      byte[] buf = new byte[8];
      long now = System.currentTimeMillis();
      buf[0] = (byte) (now >>> 56);
      buf[1] = (byte) (now >>> 48);
      // and so on


      JUSTIFICATION :
      Using ByteBuffer.putLong allows for much cleaner source code. Modifying HOTSPOT to recognize ByteBuffer.putLong and generate optimized code will allow programmers to produce cleaner source code.

      NOTE -- The test case focuses on ByteBuffer.putLong, but the same optimizations could be applied to putInt, and possibly others.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I would like ByteBuffer.putLong() to execute as fast as a series of shifts.
      ACTUAL -
      ByteBuffer.putLong() runs 25% to 30% slower than a series of assignments with shifts.

      .Time: 3.484 (testPutLongUsingShifts)
      .Time: 4.469 (testPutLongUsingByteBuffer_wrap)
      .Time: 4.422 (testPutLongUsingByteBuffer_allocate1a)
      .Time: 4.671 (testPutLongUsingByteBuffer_allocate1b)
      .Time: 4.766 (testPutLongUsingByteBuffer_allocateDirect)
      .Time: 9.516 (testPutLongUsingByteBuffer_allocate2a)
      .Time: 9.578 (testPutLongUsingByteBuffer_allocate2b)
      .Time: 9.515 (testPutLongUsingByteBuffer_wrap2)

      Time: 50.437

      OK (8 tests)

      ---------- BEGIN SOURCE ----------
      import junit.framework.TestCase;
      import java.nio.ByteBuffer;

      public class ByteBufferPerformanceTest extends TestCase {

        public static void main(String[] args) {
          junit.textui.TestRunner.run(ByteBufferPerformanceTest.class);
        }
        
        static final int times = 32000000;
        
        long begin = 0L; // initialized in setUp()
        long end = 0; // initialized in tearDown()

        protected void setUp() throws Exception {
          super.setUp();
          begin = System.currentTimeMillis();
        }

        protected void tearDown() throws Exception {
          super.tearDown();
          end = System.currentTimeMillis();
          double elapsed = (double)(end - begin) / 1000.;
          System.out.println("Time: " + elapsed + " (" + getName() + ")");
        }

        public void testPutLongUsingShifts()
        {
          byte[] buffer = new byte[16];

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            buffer[0] = (byte) (now >>> 56);
            buffer[1] = (byte) (now >>> 48);
            buffer[2] = (byte) (now >>> 40);
            buffer[3] = (byte) (now >>> 32);
            buffer[4] = (byte) (now >>> 24);
            buffer[5] = (byte) (now >>> 16);
            buffer[6] = (byte) (now >>> 8);
            buffer[7] = (byte) (now);
          }
        }

        public void testPutLongUsingByteBuffer_wrap()
        {
          byte[] buffer = new byte[16];
          ByteBuffer bb = ByteBuffer.wrap(buffer);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_allocate1a()
        {
          ByteBuffer bb = ByteBuffer.allocate(8);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_allocate1b()
        {
          ByteBuffer bb = ByteBuffer.allocate(8);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_allocateDirect()
        {
          ByteBuffer bb = ByteBuffer.allocateDirect(8);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_allocate2a()
        {
          ByteBuffer bb = ByteBuffer.allocate(8);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_allocate2b()
        {
          ByteBuffer bb = ByteBuffer.allocate(8);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }

        public void testPutLongUsingByteBuffer_wrap2()
        {
          byte[] buffer = new byte[16];
          ByteBuffer bb = ByteBuffer.wrap(buffer);

          for(int i=0; i<times; ++i)
          {
            long now = System.currentTimeMillis();
            bb.putLong(0,now);
          }
        }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Use a series of assignments with shifts as in testPutLongUsingShifts test case.
      (Incident Review ID: 301643)
      ======================================================================

            Unassigned Unassigned
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: