Here are my changes to force the JVM to execute statements (read / write) because if no value is consumed the JVM can detect it (escape analysis) and skip byte codes ...
diff --git a/allocation/TestMemoryAllocator.java b/allocation/TestMemoryAllocator.java
index 81f57e9..582076a 100644
--- a/allocation/TestMemoryAllocator.java
+++ b/allocation/TestMemoryAllocator.java
@@ -16,64 +16,71 @@
import java.util.concurrent.TimeUnit;
-import playground.memory.Allocator.Type;
public class TestMemoryAllocator {
public static void main(String...args)
{
int element = Integer.valueOf(args[1]);
-
ObjectType[] types = new ObjectType[]{ Allocator.allocate(Type.valueOf(args[0]), element)};
-
final ObjectType[] types = new ObjectType[]{ Allocator.allocate(Allocator.Type.valueOf(args[0]), element)};
int ONE_MILLION = 1000000;
-
final int len = types.length;
-
-
for(int x = 0; x < 100; x++)
{
-
for(ObjectType t : types)
-
for(int n = 0; n < len; n++)
{
-
final ObjectType t = types[n];
-
long writeStart = System.nanoTime();
-
-
int resWrite = write(t,element);
long totalWrite = System.nanoTime() - writeStart;
long readStart = System.nanoTime();
-
-
int resRead = read(t,element);
long totalRead = System.nanoTime() - readStart;
-
double writeMs = totalWrite/1000000d;
-
double readMs = totalRead/1000000d;
-
double writeMs = totalWrite / 1000000d;
-
double readMs = totalRead / 1000000d;
-
System.out.println(String.format("[%s] %s - [Write %s ms , Read %s ms ], Op/Sec(Millions)[ Write %s , Read %s ]",
-
System.out.println(String.format("[%2s] %s - [Write %16s ms , Read %16s ms ], Op/Sec(Millions)[ Write %6s , Read %6s ]: %16s %16s",
x,t.getClass().getName(), writeMs,readMs,
(TimeUnit.SECONDS.toNanos(element)/totalWrite)/ONE_MILLION,
-
(TimeUnit.SECONDS.toNanos(element)/totalRead)/ONE_MILLION));
-
(TimeUnit.SECONDS.toNanos(element)/totalRead)/ONE_MILLION,
-
-
}
-
public static void write(ObjectType t,int items)
-
public static int write(ObjectType t,int items)
{
-
for(int index=0;index<items;index++)
-
-
for(; index < items; index++)
{
t.navigate(index);
t.setByte((byte)index);
t.setInt(index);
t.setLong(index \* index);
}
-
}
@SuppressWarnings("unused")
-
public static void read(ObjectType t,int items)
-
public static int read(ObjectType t,int items)
{
-
-
-
for(int index=0;index<items;index++)
-
-
-
-
for(int index=0; index < items; index++)
{
t.navigate(index);
-
-
-
-
-
-
longSum += t.getLong();
}
-
}
}
I optimized the accesses for the HeapObject (direct access to field ie no method call and cache values[index] to be more symetric with other benchmark)
diff --git a/allocation/HeapAllocatedObject.java b/allocation/HeapAllocatedObject.java
index 2360f5b..91283a1 100644
--- a/allocation/HeapAllocatedObject.java
+++ b/allocation/HeapAllocatedObject.java
@@ -16,12 +16,14 @@
public class HeapAllocatedObject implements ObjectType {
- private HeapValue[] values;
- private int index;
-
private HeapValue[] values;
- private HeapValue cur;
public HeapAllocatedObject(int element)
{
values = new HeapValue[element];
-
for(int x=0;x<element;x++)
-
for(int x=0; x < element; x++)
{
values[x] = new HeapValue();
}
@@ -30,74 +32,46 @@ public class HeapAllocatedObject implements ObjectType {
@OverRide
public void setInt(int value) {
-
values[index].setId(value);
-
}
@OverRide
public void setLong(long value) {
-
values[index].setLongValue(value);
-
}
@OverRide
public void setByte(byte value) {
-
values[index].setType(value);
-
}
@OverRide
public int getInt() {
-
return values[index].getId();
-
}
@OverRide
public long getLong() {
-
return values[index].getLongValue();
-
}
@OverRide
public byte getByte() {
-
return values[index].getType();
-
}
-
private static class HeapValue
-
static final class HeapValue
{
-
-
- private byte type;
- }
-
public void setId(int id) {
-
- }
-
public void setLongValue(long longValue) {
-
this.longValue = longValue;
- }
-
public void setType(byte type) {
-
- }
- }
-
public long getLongValue() {
-
- }
- }
My benchmark script:
bench.sh
source ~/test-jdk8.sh
java -version
SIZE=50000000
SIZE=10000000
java -Xms2g -Xmx2g TestMemoryAllocator HEAP $SIZE
java -Xms2g -Xmx2g TestMemoryAllocator BB $SIZE
java -Xms2g -Xmx2g TestMemoryAllocator DBB $SIZE
java -Xms2g -Xmx2g TestMemoryAllocator OFFHEAP $SIZE
My benchmark results:
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b128)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)
[99] HeapAllocatedObject - [Write 76.582477 ms , Read 49.079157 ms ], Op/Sec(Millions)[ Write 130 , Read 203 ]: 10000000 -2014260032
[99] ByteBufferObject - [Write 103.398305 ms , Read 138.61927 ms ], Op/Sec(Millions)[ Write 96 , Read 72 ]: 10000000 -2014260032
[99] DirectByteBufferObject - [Write 33.876755 ms , Read 35.391567 ms ], Op/Sec(Millions)[ Write 295 , Read 282 ]: 10000000 -2014260032
[99] OffHeapObject - [Write 30.015346 ms , Read 19.307707 ms ], Op/Sec(Millions)[ Write 333 , Read 517 ]: 10000000 -2014260032