Merge pull request #109 from gianm/cache-array-base-offset
Cache arrayBaseOffset.
diff --git a/src/main/java/org/apache/datasketches/memory/BaseState.java b/src/main/java/org/apache/datasketches/memory/BaseState.java
index 8d9e12d..f8a7cf9 100644
--- a/src/main/java/org/apache/datasketches/memory/BaseState.java
+++ b/src/main/java/org/apache/datasketches/memory/BaseState.java
@@ -94,7 +94,7 @@
capacityBytes_ = capacityBytes;
cumBaseOffset_ = regionOffset + ((unsafeObj == null)
? nativeBaseOffset
- : unsafe.arrayBaseOffset(unsafeObj.getClass()));
+ : UnsafeUtil.getArrayBaseOffset(unsafeObj.getClass()));
}
//Byte Order Related
@@ -233,7 +233,7 @@
final Object unsafeObj = getUnsafeObject();
return (unsafeObj == null)
? cumBaseOffset_ - getNativeBaseOffset()
- : cumBaseOffset_ - unsafe.arrayBaseOffset(unsafeObj.getClass());
+ : cumBaseOffset_ - UnsafeUtil.getArrayBaseOffset(unsafeObj.getClass());
}
/**
@@ -518,7 +518,7 @@
uObjHeader = 0;
} else {
uObjStr = uObj.getClass().getSimpleName() + ", " + (uObj.hashCode() & 0XFFFFFFFFL);
- uObjHeader = unsafe.arrayBaseOffset(uObj.getClass());
+ uObjHeader = UnsafeUtil.getArrayBaseOffset(uObj.getClass());
}
final ByteBuffer bb = state.getByteBuffer();
final String bbStr = (bb == null) ? "null"
diff --git a/src/main/java/org/apache/datasketches/memory/UnsafeUtil.java b/src/main/java/org/apache/datasketches/memory/UnsafeUtil.java
index 7d47580..7349829 100644
--- a/src/main/java/org/apache/datasketches/memory/UnsafeUtil.java
+++ b/src/main/java/org/apache/datasketches/memory/UnsafeUtil.java
@@ -158,6 +158,35 @@
}
/**
+ * Like {@link Unsafe#arrayBaseOffset(Class)}, but caches return values for common array types. Useful because
+ * calling {@link Unsafe#arrayBaseOffset(Class)} directly incurs more overhead.
+ */
+ static long getArrayBaseOffset(final Class<?> c) {
+ // Ordering here is roughly in order of what we expect to be most popular.
+ if (c == byte[].class) {
+ return ARRAY_BYTE_BASE_OFFSET;
+ } else if (c == int[].class) {
+ return ARRAY_INT_BASE_OFFSET;
+ } else if (c == long[].class) {
+ return ARRAY_LONG_BASE_OFFSET;
+ } else if (c == float[].class) {
+ return ARRAY_FLOAT_BASE_OFFSET;
+ } else if (c == double[].class) {
+ return ARRAY_DOUBLE_BASE_OFFSET;
+ } else if (c == boolean[].class) {
+ return ARRAY_BOOLEAN_BASE_OFFSET;
+ } else if (c == short[].class) {
+ return ARRAY_SHORT_BASE_OFFSET;
+ } else if (c == char[].class) {
+ return ARRAY_CHAR_BASE_OFFSET;
+ } else if (c == Object[].class) {
+ return ARRAY_OBJECT_BASE_OFFSET;
+ } else {
+ return unsafe.arrayBaseOffset(c);
+ }
+ }
+
+ /**
* Assert the requested offset and length against the allocated size.
* The invariants equation is: {@code 0 <= reqOff <= reqLen <= reqOff + reqLen <= allocSize}.
* If this equation is violated and assertions are enabled, an {@link AssertionError} will
diff --git a/src/test/java/org/apache/datasketches/memory/UnsafeUtilTest.java b/src/test/java/org/apache/datasketches/memory/UnsafeUtilTest.java
index 2afa8e3..3c7ec09 100644
--- a/src/test/java/org/apache/datasketches/memory/UnsafeUtilTest.java
+++ b/src/test/java/org/apache/datasketches/memory/UnsafeUtilTest.java
@@ -23,6 +23,9 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import java.util.ArrayList;
+import java.util.List;
+
import org.testng.annotations.Test;
@@ -123,6 +126,30 @@
}
@Test
+ public void checkArrayBaseOffset()
+ {
+ final List<Class<?>> classes = new ArrayList<>();
+ classes.add(byte[].class);
+ classes.add(int[].class);
+ classes.add(long[].class);
+ classes.add(float[].class);
+ classes.add(double[].class);
+ classes.add(boolean[].class);
+ classes.add(short[].class);
+ classes.add(char[].class);
+ classes.add(Object[].class);
+ classes.add(byte[][].class); // An array type that is not cached
+
+ for (Class<?> clazz : classes) {
+ assertEquals(
+ UnsafeUtil.getArrayBaseOffset(clazz),
+ UnsafeUtil.unsafe.arrayBaseOffset(clazz),
+ clazz.getTypeName()
+ );
+ }
+ }
+
+ @Test
public void printlnTest() {
println("PRINTING: "+this.getClass().getName());
}