Skip to content

Instantly share code, notes, and snippets.

@arturmkrtchyan
Created January 6, 2015 21:07
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 arturmkrtchyan/99a0a552853db77db60b to your computer and use it in GitHub Desktop.
Save arturmkrtchyan/99a0a552853db77db60b to your computer and use it in GitHub Desktop.
Java Off/On Heap Struct/Object Creation
import sun.misc.Cleaner;
import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
// How to run:
// struct: javac ObjectVsStruct.java && java ObjectVsStruct struct
// object: javac ObjectVsStruct.java && java ObjectVsStruct object
public class ObjectVsStruct {
private static final int NUM_RECORDS = 20 * 1000 * 1000;
private static Buffer buffer;
private static Item[] array;
public static void main(String[] args) {
final long startTime = System.currentTimeMillis();
int numberOfRecords;
if(args != null && args.length != 0 && "struct".equals(args[0])) {
numberOfRecords = createOffHeapObjects();
} else {
numberOfRecords = createOnHeapObjects();
}
final long endTime = System.currentTimeMillis();
System.out.printf("Number of records %,d - Elapsed time: %d ms\n",
numberOfRecords, (endTime - startTime));
}
private static int createOffHeapObjects() {
buffer = new UnsafeBuffer();
buffer.allocate(NUM_RECORDS * ItemStruct.getObjectSize());
for (int i = 0; i < NUM_RECORDS; i++) {
final ItemStruct item = getItemStruct(i);
item.setId(i);
item.setKey(123);
item.setValue(777);
}
int numberOfRecords = 0;
for (int i = 0; i < NUM_RECORDS; i++) {
final ItemStruct item = getItemStruct(i);
numberOfRecords = item.getId();
}
buffer.free();
return numberOfRecords;
}
private static int createOnHeapObjects() {
array = new Item[NUM_RECORDS];
for (int i = 0; i < NUM_RECORDS; i++) {
final Item item = getItemObject(i);
item.setId(i);
item.setKey(123);
item.setValue(777);
}
int numberOfRecords = 0;
for (int i = 0; i < NUM_RECORDS; i++) {
final Item item = getItemObject(i);
numberOfRecords = item.getId();
}
return numberOfRecords;
}
private static ItemStruct getItemStruct(final int index) {
itemStruct.setObjectOffset(buffer.getOffset() + (index * ItemStruct.getObjectSize()));
return itemStruct;
}
private static Item getItemObject(final int index) {
if(array[index] == null) {
array[index] = new Item();
}
return array[index];
}
private static final ItemStruct itemStruct = new ItemStruct();
private static class ItemStruct {
private static long offset = 0;
private static final long idOffset = (offset += 0);
private static final long keyOffset = (offset += 4);
private static final long valueOffset = (offset += 4);
private static final long objectSize = offset += 4;
private long objectOffset;
public void setObjectOffset(final long objectOffset) {
this.objectOffset = objectOffset;
}
public static long getObjectSize() {
return objectSize;
}
public int getId() {
return buffer.getInt(objectOffset + idOffset);
}
public void setId(final int id) {
buffer.putInt(objectOffset + idOffset, id);
}
public int getKey() {
return buffer.getInt(objectOffset + keyOffset);
}
public void setKey(final int key) {
buffer.putInt(objectOffset + keyOffset, key);
}
public int getValue() {
return buffer.getInt(objectOffset + keyOffset);
}
public void setValue(final int valueSize) {
buffer.putInt(objectOffset + valueOffset, valueSize);
}
}
private static class Item {
private int id;
private int key;
private int value;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
private interface Buffer {
public void allocate(final long size);
public void free();
public void putInt(final long address, final int value);
public int getInt(final long address);
public long getOffset();
}
private static class UnsafeBuffer implements Buffer {
private static final Unsafe unsafe;
static {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private long address;
@Override
public void allocate(final long size) {
address = unsafe.allocateMemory(size);
}
@Override
public void free() {
unsafe.freeMemory(address);
}
@Override
public long getOffset() {
return address;
}
@Override
public void putInt(long address, int value) {
unsafe.putInt(address, value);
}
@Override
public int getInt(long address) {
return unsafe.getInt(address);
}
}
private static class HeapByteBuffer implements Buffer {
private ByteBuffer buffer;
@Override
public void allocate(final long size) {
buffer = ByteBuffer.allocate((int)size);
}
@Override
public void free() {
}
@Override
public void putInt(long address, int value) {
buffer.putInt((int)address, value);
}
@Override
public int getInt(long address) {
return buffer.getInt((int) address);
}
@Override
public long getOffset() {
return 0;
}
}
private static class DirectByteBuffer implements Buffer {
private ByteBuffer buffer;
@Override
public void allocate(final long size) {
buffer = ByteBuffer.allocateDirect((int) size);
}
@Override
public void free() {
Cleaner cleaner = ((DirectBuffer)buffer).cleaner();
if (cleaner != null) cleaner.clean();
}
@Override
public void putInt(long address, int value) {
buffer.putInt((int)address, value);
}
@Override
public int getInt(long address) {
return buffer.getInt((int) address);
}
@Override
public long getOffset() {
return 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment