Created
June 29, 2013 01:00
-
-
Save burtonator/5889192 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.netty.buffer; | |
import io.netty.util.internal.JavassistTypeParameterMatcherGenerator; | |
import sun.misc.Unsafe; | |
import sun.nio.ch.DirectBuffer; | |
import java.lang.reflect.Field; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
/** | |
* | |
*/ | |
public class Test { | |
private static Unsafe UNSAFE = null; | |
public static void testWithUnsafe( String desc, ByteBuffer buff ) { | |
desc = String.format( "%s (%s)", desc, buff.getClass().getName() ); | |
System.out.printf( "----------------\n" ); | |
System.out.printf( "%s\n", desc ); | |
List<Long> durations = new ArrayList<Long>(); | |
// test filling it with bytes... | |
System.out.printf( "class impl: %s (order=%s)\n", buff.getClass().getName(), buff.order() ); | |
long memoryAddress = ((DirectBuffer) buff).address(); | |
for( int j = 0; j < 2; ++j ) { | |
long before = System.currentTimeMillis(); | |
long offset = memoryAddress; | |
long end = memoryAddress + buff.capacity(); | |
int val = 666; | |
while( offset < end ) { | |
UNSAFE.putInt( offset, val ); | |
offset += 4; | |
} | |
offset = memoryAddress; | |
while( offset < end ) { | |
int result = UNSAFE.getInt( offset ); | |
if ( result != val ) | |
throw new RuntimeException(); | |
offset += 4; | |
} | |
long after = System.currentTimeMillis(); | |
long duration = (after-before); | |
System.out.printf( "Duration: %,d ms\n", duration ); | |
durations.add( duration ); | |
//System.gc(); | |
} | |
long mean = mean( durations ); | |
System.out.printf( "Final mean duration: %,d ms\n", mean ); | |
results.add( new Result( mean, desc ) ); | |
} | |
public static void test( String desc, ByteBuffer buff ) { | |
desc = String.format( "%s (%s)", desc, buff.getClass().getName() ); | |
System.out.printf( "----------------\n" ); | |
System.out.printf( "%s\n", desc ); | |
List<Long> durations = new ArrayList<Long>(); | |
// test filling it with bytes... | |
System.out.printf( "class impl: %s (order=%s)\n", buff.getClass().getName(), buff.order() ); | |
for( int j = 0; j < 2; ++j ) { | |
long before = System.currentTimeMillis(); | |
buff.position(0); | |
for( int i = 0; i < buff.capacity() / 4; ++i ) { | |
buff.putInt( i ); | |
} | |
buff.position(0); | |
for( int i = 0; i < buff.capacity() / 4; ++i ) { | |
int val = buff.getInt(); | |
if ( i != val ) { | |
throw new RuntimeException( String.format( "invalid int read: %s vs %s", i, val ) ); | |
} | |
} | |
long after = System.currentTimeMillis(); | |
long duration = (after-before); | |
System.out.printf( "Duration: %,d ms\n", duration ); | |
durations.add( duration ); | |
System.gc(); | |
} | |
long mean = mean( durations ); | |
System.out.printf( "Final mean duration: %,d ms\n", mean ); | |
results.add( new Result( mean, desc ) ); | |
} | |
public static void test( String desc, ByteBuf buff ) { | |
desc = String.format( "%s (%s)", desc, buff.getClass().getName() ); | |
System.out.printf( "----------------\n" ); | |
System.out.printf( "%s\n", desc ); | |
List<Long> durations = new ArrayList<Long>(); | |
// test filling it with bytes... | |
System.out.printf( "class impl: %s (order=%s)\n", buff.getClass().getName(), buff.order() ); | |
for( int j = 0; j < 2; ++j ) { | |
long before = System.currentTimeMillis(); | |
buff.readerIndex(0); | |
buff.writerIndex(0); | |
for( int i = 0; i < buff.capacity() / 4; ++i ) { | |
buff.writeInt( i ); | |
} | |
for( int i = 0; i < buff.capacity() / 4; ++i ) { | |
int val = buff.readInt(); | |
if ( i != val ) { | |
throw new RuntimeException( "invalid int read: " + i ); | |
} | |
} | |
long after = System.currentTimeMillis(); | |
long duration = (after-before); | |
System.out.printf( "Duration: %,d ms\n", duration ); | |
durations.add( duration ); | |
System.gc(); | |
} | |
long mean = mean( durations ); | |
System.out.printf( "Final mean duration: %,d ms\n", mean ); | |
results.add( new Result( mean, desc ) ); | |
} | |
public static void main(String[] args) throws Exception { | |
UNSAFE = getUnsafe(); | |
int capacity = 500000000; | |
System.out.printf( "Native byte order: %s\n", ByteOrder.nativeOrder() ); | |
testWithUnsafe( "Gold standard direct byte buffer via Unsafe.", ByteBuffer.allocateDirect( capacity ).order( ByteOrder.LITTLE_ENDIAN ) ); | |
test( "regular direct ByteBuffer", ByteBuffer.allocateDirect( capacity ) ); | |
test( "regular direct ByteBuffer after changing order (BIG_ENDIAN)", ByteBuffer.allocateDirect( capacity ).order( ByteOrder.BIG_ENDIAN ) ); | |
test( "regular direct ByteBuffer after changing order (LITTLE_ENDIAN)", ByteBuffer.allocateDirect( capacity ).order( ByteOrder.LITTLE_ENDIAN ) ); | |
test( "regular heap ByteBuffer", ByteBuffer.allocate( capacity ) ); | |
test( "regular heap ByteBuffer after changing order (BIG_ENDIAN)", ByteBuffer.allocate( capacity ).order( ByteOrder.BIG_ENDIAN ) ); | |
test( "regular heap ByteBuffer after changing order (LITTLE_ENDIAN)", ByteBuffer.allocate( capacity ).order( ByteOrder.LITTLE_ENDIAN ) ); | |
test( "Netty Unpooled directBuffer", Unpooled.directBuffer(capacity) ); | |
test( "Netty Unpooled directBuffer with set ByteOrder (BIG_ENDIAN)", Unpooled.directBuffer(capacity).order( ByteOrder.BIG_ENDIAN ) ); | |
test( "Netty Unpooled.directBuffer with set ByteOrder (LITTLE_ENDIAN)", Unpooled.directBuffer( capacity ).order( ByteOrder.LITTLE_ENDIAN ) ); | |
test( "Netty Unpooled heap buffer", Unpooled.buffer(capacity) ); | |
test( "Netty Unpooled heap buffer with set ByteOrder (BIG_ENDIAN)", Unpooled.buffer(capacity).order( ByteOrder.BIG_ENDIAN) ); | |
test( "Netty Unpooled heap buffer with set ByteOrder (LITTLE_ENDIAN)", Unpooled.buffer(capacity).order( ByteOrder.LITTLE_ENDIAN) ); | |
/* | |
test( "Test with UnpooledUnsafeDirectByteBuf and manually setting the ByteOrder on the underlying ByteBuff (BIG_ENDIAN):", unpooledUnsafeDirectByteBuf ); | |
unpooledUnsafeDirectByteBuf = new UnpooledUnsafeDirectByteBuf(UnpooledByteBufAllocator.DEFAULT, capacity, capacity); | |
unpooledUnsafeDirectByteBuf.getByteBuffer().order( ByteOrder.LITTLE_ENDIAN ); | |
test( "Test with UnpooledUnsafeDirectByteBuf and manually setting the ByteOrder on the underlying ByteBuff (LITTLE_ENDIAN):", unpooledUnsafeDirectByteBuf ); | |
*/ | |
report(); | |
} | |
public static Unsafe getUnsafe() throws Exception { | |
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); | |
unsafeField.setAccessible(true); | |
return (Unsafe) unsafeField.get(null); | |
} | |
public static long mean( List<Long> list ) { | |
long sum = 0; | |
for( long d : list ) { | |
sum += d; | |
} | |
return sum / list.size(); | |
} | |
// report our results | |
public static void report() { | |
System.out.printf( "=========================\n" ); | |
System.out.printf( "Report:\n" ); | |
Collections.sort( results ); | |
for( Result result : results ) { | |
System.out.printf( "%s\n", result ); | |
} | |
} | |
public static List<Result> results = new ArrayList<Result>(); | |
public static class Result implements Comparable<Result> { | |
public long duration; | |
public String name; | |
public Result(long duration, String name) { | |
this.duration = duration; | |
this.name = name; | |
} | |
@Override | |
public int compareTo(Result o) { | |
return (int)duration - (int)o.duration; | |
} | |
@Override | |
public String toString() { | |
return String.format( "%-120s %,d ms", name, duration ); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment