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)
======================================================================
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)
======================================================================
- duplicates
-
JDK-8026049 (bf) Intrinsify ByteBuffer.put{Int,Double,Float,...} methods
- Resolved