Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edefazio/85cd0c1264a0938b88a8 to your computer and use it in GitHub Desktop.
Save edefazio/85cd0c1264a0938b88a8 to your computer and use it in GitHub Desktop.
Unsafe.allocateMemory(...) performs 2x BETTER when we pass in an int verses a long (of the same value)
package strangeunsafe;
import java.lang.reflect.Field;
import java.util.Random;
import sun.misc.Unsafe
/**
* Illustrate "strange" issue where Unsafe.allocateMemory(...) performs BETTER
* when we pass in an int parameter verses a long parameter (of the same value).
* (more detail in description)
* <PRE>
* Took 665ms to scan LANE 1 100000 8bit bytes 10000x and find 197690000
* Took 1138ms to scan LANE 2 100000 8bit bytes 10000x and find 197690000
*
* Took 6597ms to scan LANE 1 100000000 8bit bytes 100x and find 2000811000
* Took 11335ms to scan LANE 2 100000000 8bit bytes 100x and find 2000811000
*
* Took 6489ms to scan LANE 1 100000000 8bit bytes 100x and find 1999797500
* Took 11319ms to scan LANE 2 100000000 8bit bytes 100x and find 1999797500
* </PRE>
*/
public class UnsafeAllocateMemoryConstructorEffectsScanPerformance
{
public static final int LANE1_DATASET_SIZE = 100000000;
public static final long LANE2_DATASET_SIZE = LANE1_DATASET_SIZE;
public static final long ITERATIONS = 100;
public static void main ( String[] args )
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
Unsafe theUnsafe = getUnsafe();
//NOTE: the addresses are BOTH longs
long startLane1 = theUnsafe.allocateMemory( LANE1_DATASET_SIZE );
long startLane2 = theUnsafe.allocateMemory( LANE2_DATASET_SIZE );
// I "thought" perhaps there was some optimization going on
// with the addressing, but BOTH of the addresses SEEM to be
// using only 31/32-bits of the 64-bit address...
// (so both physical memory addresses are using only 32-bits of the 64-bits)
System.out.println ("LANE1 MEMORY ADDRESS BINARY "+ Long.toString ( startLane1 , 2 ) );
System.out.println ("LANE2 MEMORY ADDRESS BINARY "+ Long.toString ( startLane2 , 2 ) );
Random r = new Random();
long lane1Address = startLane1;
long lane2Address = startLane2;
for ( int i = 0; i < LANE1_DATASET_SIZE; i++ )
{
//populate data [1...5] in each byte (the same data in each "lane")
byte oneTo5 = (byte) ( r.nextInt( 5 ) + 1 );
theUnsafe.putByte( lane1Address, oneTo5 );
theUnsafe.putByte( lane2Address, oneTo5 );
lane1Address++;
lane2Address++;
}
long start = System.currentTimeMillis();
//lets scan through lane1, counting the number of matches
int count = 0;
for ( int it = 0; it < ITERATIONS; it++ )
{
lane1Address = startLane1;
for ( int i = 0; i < LANE1_DATASET_SIZE; i++ )
{
if ( theUnsafe.getByte( lane1Address ) == 5 )
{
count++;
}
lane1Address++;
}
}
long end = System.currentTimeMillis();
System.out.println ("Took "+(end-start)+"ms to scan LANE 1 "+ LANE1_DATASET_SIZE+" 8bit bytes "+ITERATIONS+"x and find "+count);
theUnsafe.freeMemory( startLane1 );
//lets do the same with lane 2
start = System.currentTimeMillis(); //RESET START
count = 0;
for ( int it = 0; it < ITERATIONS; it++ )
{
lane2Address = startLane2;
for ( int i = 0; i < LANE2_DATASET_SIZE; i++ )
{
if ( theUnsafe.getByte( lane2Address ) == 5 )
{
count++;
}
lane2Address++;
}
}
end = System.currentTimeMillis();
System.out.println ("Took "+(end-start)+"ms to scan LANE 2 "+ LANE1_DATASET_SIZE+" 8bit bytes "+ITERATIONS+"x and find "+count);
theUnsafe.freeMemory( startLane2 );
}
private static Unsafe getUnsafe()
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
return unsafe;
}
}
@edefazio
Copy link
Author

edefazio commented Nov 1, 2015

Nitsan's (Video) "The Illusion of Execution" describing JVM execution.
The whole video is great, relevant to this faux paus (non-counted Loops and safe points) starts at about ~12:15:
https://vimeo.com/138863976

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment