>From Wail Alkowaileet <[email protected]>:
Wail Alkowaileet has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17421 )
Change subject: [WIP] Utilize unsafe
......................................................................
[WIP] Utilize unsafe
Details:
The micro benchmark shows ~4.5x improvment for
writing long values and ~2.4x for reading
Example for writing/reading 1M long value
Writing unsafe took: 585958
Unsafe avg time to read: 35972
Writing safe took: 2726958
Safe avg time to read: 86079
Change-Id: Icd8f8862ce03553ce2a3b6f8e1a8131bb2b78761
---
A
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
M
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
M
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
A
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
M
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
A
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
A
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
M
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
A
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
A
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
M
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
A
hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
A
hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
A
hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
M
hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
15 files changed, 754 insertions(+), 61 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/21/17421/1
diff --git
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
index cba8e63..43e706d 100644
---
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
+++
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/serializable/std/BufferSerDeUtil.java
@@ -18,68 +18,48 @@
*/
package org.apache.asterix.runtime.aggregates.serializable.std;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
public class BufferSerDeUtil {
public static double getDouble(byte[] bytes, int offset) {
- return Double.longBitsToDouble(getLong(bytes, offset));
+ return ACCESSOR.getDouble(bytes, offset);
}
public static float getFloat(byte[] bytes, int offset) {
- return Float.intBitsToFloat(getInt(bytes, offset));
+ return ACCESSOR.getFloat(bytes, offset);
}
public static boolean getBoolean(byte[] bytes, int offset) {
- if (bytes[offset] == 0)
- return false;
- else
- return true;
+ return bytes[offset] != 0;
}
public static int getInt(byte[] bytes, int offset) {
- return ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) <<
16) + ((bytes[offset + 2] & 0xff) << 8)
- + ((bytes[offset + 3] & 0xff) << 0);
+ return ACCESSOR.getInt(bytes, offset);
}
public static long getLong(byte[] bytes, int offset) {
- return (((long) (bytes[offset] & 0xff)) << 56) + (((long)
(bytes[offset + 1] & 0xff)) << 48)
- + (((long) (bytes[offset + 2] & 0xff)) << 40) + (((long)
(bytes[offset + 3] & 0xff)) << 32)
- + (((long) (bytes[offset + 4] & 0xff)) << 24) + (((long)
(bytes[offset + 5] & 0xff)) << 16)
- + (((long) (bytes[offset + 6] & 0xff)) << 8) + (((long)
(bytes[offset + 7] & 0xff)) << 0);
+ return ACCESSOR.getLong(bytes, offset);
}
public static void writeBoolean(boolean value, byte[] bytes, int offset) {
- if (value)
- bytes[offset] = (byte) 1;
- else
- bytes[offset] = (byte) 0;
+ bytes[offset] = (byte) (value ? 1 : 0);
}
public static void writeInt(int value, byte[] bytes, int offset) {
- bytes[offset++] = (byte) (value >> 24);
- bytes[offset++] = (byte) (value >> 16);
- bytes[offset++] = (byte) (value >> 8);
- bytes[offset++] = (byte) (value);
+ ACCESSOR.putInt(bytes, offset, value);
}
public static void writeLong(long value, byte[] bytes, int offset) {
- bytes[offset++] = (byte) (value >> 56);
- bytes[offset++] = (byte) (value >> 48);
- bytes[offset++] = (byte) (value >> 40);
- bytes[offset++] = (byte) (value >> 32);
- bytes[offset++] = (byte) (value >> 24);
- bytes[offset++] = (byte) (value >> 16);
- bytes[offset++] = (byte) (value >> 8);
- bytes[offset++] = (byte) (value);
+ ACCESSOR.putLong(bytes, offset, value);
}
public static void writeDouble(double value, byte[] bytes, int offset) {
- long lValue = Double.doubleToLongBits(value);
- writeLong(lValue, bytes, offset);
+ ACCESSOR.putDouble(bytes, offset, value);
}
public static void writeFloat(float value, byte[] bytes, int offset) {
- int iValue = Float.floatToIntBits(value);
- writeInt(iValue, bytes, offset);
+ ACCESSOR.putFloat(bytes, offset, value);
}
}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
new file mode 100644
index 0000000..31fe95d
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/ByteAccessorProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class ByteAccessorProvider {
+ private static final Logger LOGGER = LogManager.getLogger();
+ public static final IByteValueAccessor ACCESSOR = getAccessor();
+
+ private static IByteValueAccessor getAccessor() {
+ if (UnsafeByteValueAccessor.isAccessible()) {
+ LOGGER.debug("Unsafe byte accessor is initialized");
+ return UnsafeByteValueAccessor.INSTANCE;
+ }
+ LOGGER.debug("Safe byte accessor is initialized");
+ return SafeByteValueAccessor.INSTANCE;
+ }
+
+ private ByteAccessorProvider() {
+ }
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
new file mode 100644
index 0000000..4fb7c59
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/IByteValueAccessor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+public interface IByteValueAccessor {
+ byte getByte(byte[] bytes, int offset);
+
+ short getShort(byte[] bytes, int offset);
+
+ int getInt(byte[] bytes, int offset);
+
+ long getLong(byte[] bytes, int offset);
+
+ float getFloat(byte[] bytes, int offset);
+
+ double getDouble(byte[] bytes, int offset);
+
+ void putByte(byte[] bytes, int offset, byte value);
+
+ void putShort(byte[] bytes, int offset, short value);
+
+ void putInt(byte[] bytes, int offset, int value);
+
+ void putLong(byte[] bytes, int offset, long value);
+
+ void putFloat(byte[] bytes, int offset, float value);
+
+ void putDouble(byte[] bytes, int offset, double value);
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
new file mode 100644
index 0000000..1799fe0
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/SafeByteValueAccessor.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+final class SafeByteValueAccessor implements IByteValueAccessor {
+ static final IByteValueAccessor INSTANCE = new SafeByteValueAccessor();
+
+ private SafeByteValueAccessor() {
+ }
+
+ @Override
+ public byte getByte(byte[] bytes, int offset) {
+ return bytes[offset];
+ }
+
+ @Override
+ public short getShort(byte[] bytes, int offset) {
+ return (short) (((bytes[offset] & 0xff) << 8) + (bytes[offset + 1] &
0xff));
+ }
+
+ @Override
+ public int getInt(byte[] bytes, int offset) {
+ return ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) <<
16) + ((bytes[offset + 2] & 0xff) << 8)
+ + ((bytes[offset + 3] & 0xff));
+ }
+
+ @Override
+ public long getLong(byte[] bytes, int offset) {
+ return (((long) (bytes[offset] & 0xff)) << 56) + (((long)
(bytes[offset + 1] & 0xff)) << 48)
+ + (((long) (bytes[offset + 2] & 0xff)) << 40) + (((long)
(bytes[offset + 3] & 0xff)) << 32)
+ + (((long) (bytes[offset + 4] & 0xff)) << 24) + (((long)
(bytes[offset + 5] & 0xff)) << 16)
+ + (((long) (bytes[offset + 6] & 0xff)) << 8) + (((long)
(bytes[offset + 7] & 0xff)));
+ }
+
+ @Override
+ public float getFloat(byte[] bytes, int offset) {
+ int bits = getInt(bytes, offset);
+ return Float.intBitsToFloat(bits);
+ }
+
+ @Override
+ public double getDouble(byte[] bytes, int offset) {
+ long bits = getLong(bytes, offset);
+ return Double.longBitsToDouble(bits);
+ }
+
+ @Override
+ public void putByte(byte[] bytes, int offset, byte value) {
+ bytes[offset] = value;
+ }
+
+ @Override
+ public void putShort(byte[] bytes, int offset, short value) {
+ bytes[offset] = (byte) ((value >>> 8) & 0xFF);
+ bytes[offset + 1] = (byte) ((value) & 0xFF);
+ }
+
+ @Override
+ public void putInt(byte[] bytes, int offset, int value) {
+ bytes[offset] = (byte) ((value >>> 24) & 0xFF);
+ bytes[offset + 1] = (byte) ((value >>> 16) & 0xFF);
+ bytes[offset + 2] = (byte) ((value >>> 8) & 0xFF);
+ bytes[offset + 3] = (byte) (value & 0xFF);
+ }
+
+ @Override
+ public void putLong(byte[] bytes, int offset, long value) {
+ bytes[offset] = (byte) ((value >>> 56) & 0xFF);
+ bytes[offset + 1] = (byte) ((value >>> 48) & 0xFF);
+ bytes[offset + 2] = (byte) ((value >>> 40) & 0xFF);
+ bytes[offset + 3] = (byte) ((value >>> 32) & 0xFF);
+ bytes[offset + 4] = (byte) ((value >>> 24) & 0xFF);
+ bytes[offset + 5] = (byte) ((value >>> 16) & 0xFF);
+ bytes[offset + 6] = (byte) ((value >>> 8) & 0xFF);
+ bytes[offset + 7] = (byte) (value & 0xFF);
+ }
+
+ @Override
+ public void putFloat(byte[] bytes, int offset, float value) {
+ int bits = Float.floatToIntBits(value);
+ putInt(bytes, offset, bits);
+ }
+
+ @Override
+ public void putDouble(byte[] bytes, int offset, double value) {
+ long bits = Double.doubleToLongBits(value);
+ putLong(bytes, offset, bits);
+ }
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
new file mode 100644
index 0000000..b0060f2
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/bytes/UnsafeByteValueAccessor.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+final class UnsafeByteValueAccessor implements IByteValueAccessor {
+ static final IByteValueAccessor INSTANCE = new UnsafeByteValueAccessor();
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+
+ private static final long BYTE_ARRAY_BASE_OFFSET =
UNSAFE.arrayBaseOffset(byte[].class);
+
+ static sun.misc.Unsafe getUnsafe() {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe = AccessController.doPrivileged(new
PrivilegedExceptionAction<>() {
+ @Override
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+ for (Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+ // do nothing
+ }
+ return unsafe;
+ }
+
+ static boolean isAccessible() {
+ return UNSAFE != null;
+ }
+
+ private UnsafeByteValueAccessor() {
+ }
+
+ @Override
+ public byte getByte(byte[] bytes, int offset) {
+ return UNSAFE.getByte(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ @Override
+ public short getShort(byte[] bytes, int offset) {
+ return UNSAFE.getShort(bytes, offset);
+ }
+
+ @Override
+ public int getInt(byte[] bytes, int offset) {
+ return UNSAFE.getInt(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ @Override
+ public long getLong(byte[] bytes, int offset) {
+ return UNSAFE.getLong(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ @Override
+ public float getFloat(byte[] bytes, int offset) {
+ return UNSAFE.getFloat(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ @Override
+ public double getDouble(byte[] bytes, int offset) {
+ return UNSAFE.getDouble(bytes, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ @Override
+ public void putByte(byte[] bytes, int offset, byte value) {
+ UNSAFE.putByte(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+
+ @Override
+ public void putShort(byte[] bytes, int offset, short value) {
+ UNSAFE.putShort(bytes, offset, value);
+ }
+
+ @Override
+ public void putInt(byte[] bytes, int offset, int value) {
+ UNSAFE.putInt(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+
+ @Override
+ public void putLong(byte[] bytes, int offset, long value) {
+ UNSAFE.putLong(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+
+ @Override
+ public void putFloat(byte[] bytes, int offset, float value) {
+ UNSAFE.putFloat(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+
+ @Override
+ public void putDouble(byte[] bytes, int offset, double value) {
+ UNSAFE.putDouble(bytes, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
new file mode 100644
index 0000000..4321ed4
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/AbstractPutGetTest.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+import java.util.Random;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+abstract class AbstractPutGetTest {
+ private static final int TEST_LENGTH = 100;
+ private final IByteValueAccessor ACCESSOR;
+ private final Random random;
+
+ public AbstractPutGetTest() {
+ random = new Random(0);
+ ACCESSOR = getAccessor();
+ }
+
+ protected abstract IByteValueAccessor getAccessor();
+
+ @Test
+ public void testByte() {
+ int valueLength = Byte.BYTES;
+ byte[] values = new byte[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ byte value = (byte) random.nextInt();
+ values[i] = value;
+ ACCESSOR.putByte(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getByte(accessorBytes, i *
valueLength));
+ }
+ }
+
+ @Test
+ public void testShort() {
+ int valueLength = Short.BYTES;
+ short[] values = new short[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ short value = (short) random.nextInt();
+ values[i] = value;
+ ACCESSOR.putShort(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getShort(accessorBytes, i
* valueLength));
+ }
+ }
+
+ @Test
+ public void testInt() {
+ int valueLength = Integer.BYTES;
+ int[] values = new int[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ int value = random.nextInt();
+ values[i] = value;
+ ACCESSOR.putInt(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getInt(accessorBytes, i *
valueLength));
+ }
+ }
+
+ @Test
+ public void testLong() {
+ int valueLength = Long.BYTES;
+ long[] values = new long[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ long value = random.nextLong();
+ values[i] = value;
+ ACCESSOR.putLong(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getLong(accessorBytes, i *
valueLength));
+ }
+ }
+
+ @Test
+ public void testFloat() {
+ int valueLength = Float.BYTES;
+ float[] values = new float[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ float value = random.nextFloat();
+ values[i] = value;
+ ACCESSOR.putFloat(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getFloat(accessorBytes, i
* valueLength), 0);
+ }
+ }
+
+ @Test
+ public void testDouble() {
+ int valueLength = Double.BYTES;
+ double[] values = new double[TEST_LENGTH];
+ byte[] accessorBytes = new byte[TEST_LENGTH * valueLength];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ double value = random.nextDouble();
+ values[i] = value;
+ ACCESSOR.putDouble(accessorBytes, i * valueLength, value);
+ }
+
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ Assert.assertEquals(values[i], ACCESSOR.getDouble(accessorBytes, i
* valueLength), 0);
+ }
+ }
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
new file mode 100644
index 0000000..3b69c8c
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/MicroBenchmarkTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+import java.util.Random;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore
+public class MicroBenchmarkTest {
+ private static final int TEST_LENGTH = 1000000;
+ private static final int NUMBER_OF_ITERATIONS = 20;
+
+ @Test
+ public void run() {
+ Random random = new Random(0);
+ long[] values = new long[TEST_LENGTH];
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ values[i] = random.nextLong();
+ }
+ byte[] unsafeBytes = new byte[TEST_LENGTH * Long.BYTES];
+ byte[] safeBytes = new byte[TEST_LENGTH * Long.BYTES];
+
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ runUnsafe(unsafeBytes, values);
+ System.out.println();
+ runSafe(safeBytes, values);
+ System.out.println("========================");
+ System.out.println();
+ }
+
+ }
+
+ private void runSafe(byte[] bytes, long[] values) {
+ IByteValueAccessor accessor = SafeByteValueAccessor.INSTANCE;
+ System.out.println("Writing safe took: " + write(accessor, values,
bytes));
+
+ long start = System.nanoTime();
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ read(accessor, bytes);
+ }
+ long avgTime = (System.nanoTime() - start) / NUMBER_OF_ITERATIONS;
+ System.out.println("Safe avg time to read: " + avgTime);
+ }
+
+ private void runUnsafe(byte[] bytes, long[] values) {
+ IByteValueAccessor accessor = UnsafeByteValueAccessor.INSTANCE;
+ System.out.println("Writing unsafe took: " + write(accessor, values,
bytes));
+
+ long start = System.nanoTime();
+ for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
+ read(accessor, bytes);
+ }
+ long avgTime = (System.nanoTime() - start) / NUMBER_OF_ITERATIONS;
+ System.out.println("Unsafe avg time to read: " + avgTime);
+ }
+
+ private void read(IByteValueAccessor accessor, byte[] bytes) {
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ accessor.getLong(bytes, i * Long.BYTES);
+ }
+ }
+
+ private long write(IByteValueAccessor accessor, long[] values, byte[]
bytes) {
+
+ long start = System.nanoTime();
+ for (int i = 0; i < TEST_LENGTH; i++) {
+ accessor.putLong(bytes, i * Long.BYTES, values[i]);
+ }
+ return System.nanoTime() - start;
+ }
+
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
new file mode 100644
index 0000000..29e8eb2
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/SafePutGetTest.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+public class SafePutGetTest extends AbstractPutGetTest {
+
+ @Override
+ protected IByteValueAccessor getAccessor() {
+ return SafeByteValueAccessor.INSTANCE;
+ }
+
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
new file mode 100644
index 0000000..9d25bb1
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/bytes/UnsafePutGetTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.bytes;
+
+public class UnsafePutGetTest extends AbstractPutGetTest {
+ @Override
+ protected IByteValueAccessor getAccessor() {
+ if (UnsafeByteValueAccessor.isAccessible()) {
+ return UnsafeByteValueAccessor.INSTANCE;
+ } else {
+ // Allow the test to proceed successfully
+ System.err.println("Cannot access unsafe object");
+ return SafeByteValueAccessor.INSTANCE;
+ }
+ }
+}
diff --git
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
index 4f5d0a1..1680f5a 100644
---
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
+++
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/DoublePointable.java
@@ -18,6 +18,8 @@
*/
package org.apache.hyracks.data.std.primitive;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
@@ -84,13 +86,11 @@
}
public static double getDouble(byte[] bytes, int start) {
- long bits = getLongBits(bytes, start);
- return Double.longBitsToDouble(bits);
+ return ACCESSOR.getDouble(bytes, start);
}
public static void setDouble(byte[] bytes, int start, double value) {
- long bits = Double.doubleToLongBits(value);
- LongPointable.setLong(bytes, start, bits);
+ ACCESSOR.putDouble(bytes, start, value);
}
public double getDouble() {
diff --git
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
index 7c72d5c..aa08b47 100644
---
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
+++
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
@@ -18,6 +18,8 @@
*/
package org.apache.hyracks.data.std.primitive;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
@@ -67,13 +69,11 @@
}
public static float getFloat(byte[] bytes, int start) {
- int bits = getIntBits(bytes, start);
- return Float.intBitsToFloat(bits);
+ return ACCESSOR.getFloat(bytes, start);
}
public static void setFloat(byte[] bytes, int start, float value) {
- int bits = Float.floatToIntBits(value);
- IntegerPointable.setInteger(bytes, start, bits);
+ ACCESSOR.putFloat(bytes, start, value);
}
public float getFloat() {
diff --git
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
index ad80e23..effc791 100644
---
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
+++
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/IntegerPointable.java
@@ -18,6 +18,8 @@
*/
package org.apache.hyracks.data.std.primitive;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
@@ -71,15 +73,11 @@
}
public static int getInteger(byte[] bytes, int start) {
- return ((bytes[start] & 0xff) << 24) + ((bytes[start + 1] & 0xff) <<
16) + ((bytes[start + 2] & 0xff) << 8)
- + ((bytes[start + 3] & 0xff) << 0);
+ return ACCESSOR.getInt(bytes, start);
}
public static void setInteger(byte[] bytes, int start, int value) {
- bytes[start] = (byte) ((value >>> 24) & 0xFF);
- bytes[start + 1] = (byte) ((value >>> 16) & 0xFF);
- bytes[start + 2] = (byte) ((value >>> 8) & 0xFF);
- bytes[start + 3] = (byte) ((value >>> 0) & 0xFF);
+ ACCESSOR.putInt(bytes, start, value);
}
public int getInteger() {
diff --git
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
index 2de7b82..faabfcf 100644
---
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
+++
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/LongPointable.java
@@ -18,6 +18,8 @@
*/
package org.apache.hyracks.data.std.primitive;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
@@ -72,21 +74,11 @@
}
public static long getLong(byte[] bytes, int start) {
- return (((long) (bytes[start] & 0xff)) << 56) + (((long) (bytes[start
+ 1] & 0xff)) << 48)
- + (((long) (bytes[start + 2] & 0xff)) << 40) + (((long)
(bytes[start + 3] & 0xff)) << 32)
- + (((long) (bytes[start + 4] & 0xff)) << 24) + (((long)
(bytes[start + 5] & 0xff)) << 16)
- + (((long) (bytes[start + 6] & 0xff)) << 8) + (((long)
(bytes[start + 7] & 0xff)) << 0);
+ return ACCESSOR.getLong(bytes, start);
}
public static void setLong(byte[] bytes, int start, long value) {
- bytes[start] = (byte) ((value >>> 56) & 0xFF);
- bytes[start + 1] = (byte) ((value >>> 48) & 0xFF);
- bytes[start + 2] = (byte) ((value >>> 40) & 0xFF);
- bytes[start + 3] = (byte) ((value >>> 32) & 0xFF);
- bytes[start + 4] = (byte) ((value >>> 24) & 0xFF);
- bytes[start + 5] = (byte) ((value >>> 16) & 0xFF);
- bytes[start + 6] = (byte) ((value >>> 8) & 0xFF);
- bytes[start + 7] = (byte) ((value >>> 0) & 0xFF);
+ ACCESSOR.putLong(bytes, start, value);
}
public long getLong() {
diff --git
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
index 3806c0c..4bc5c90 100644
---
a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
+++
b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/ShortPointable.java
@@ -18,6 +18,8 @@
*/
package org.apache.hyracks.data.std.primitive;
+import static org.apache.hyracks.bytes.ByteAccessorProvider.ACCESSOR;
+
import org.apache.hyracks.api.dataflow.value.ITypeTraits;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.io.IJsonSerializable;
@@ -63,12 +65,11 @@
}
public static short getShort(byte[] bytes, int start) {
- return (short) (((bytes[start] & 0xff) << 8) + (bytes[start + 1] &
0xff));
+ return ACCESSOR.getShort(bytes, start);
}
public static void setShort(byte[] bytes, int start, short value) {
- bytes[start] = (byte) ((value >>> 8) & 0xFF);
- bytes[start + 1] = (byte) ((value >>> 0) & 0xFF);
+ ACCESSOR.putShort(bytes, start, value);
}
public short getShort() {
diff --git
a/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
new file mode 100644
index 0000000..152b208
--- /dev/null
+++
b/hyracks-fullstack/hyracks/hyracks-storage-am-lsm-btree-column/src/main/java/org/apache/hyracks/storage/am/lsm/btree/column/utils/UnsafeUtil.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.storage.am.lsm.btree.column.utils;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * Unsafe accessor to serialize/deserialize bytes. This is intended for
little-indian machines
+ */
+@SuppressWarnings("restriction")
+public class UnsafeUtil {
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+
+ private static final long BYTE_ARRAY_BASE_OFFSET =
UNSAFE.arrayBaseOffset(byte[].class);
+
+ private UnsafeUtil() {
+
+ }
+
+ static sun.misc.Unsafe getUnsafe() {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe = AccessController.doPrivileged(new
PrivilegedExceptionAction<>() {
+ @Override
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+ for (Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+
+ }
+ return unsafe;
+ }
+
+ public static byte getByte(byte[] target, int offset) {
+ return UNSAFE.getByte(target, BYTE_ARRAY_BASE_OFFSET + offset);
+ }
+
+ public static void putByte(Object target, int offset, byte value) {
+ UNSAFE.putByte(target, BYTE_ARRAY_BASE_OFFSET + offset, value);
+ }
+
+ public static short getShort(byte[] target, int offset) {
+ return Short.reverseBytes(UNSAFE.getShort(target,
BYTE_ARRAY_BASE_OFFSET + offset));
+ }
+
+ public static void putShort(Object target, int offset, short value) {
+ UNSAFE.putShort(target, BYTE_ARRAY_BASE_OFFSET + offset,
Short.reverseBytes(value));
+ }
+
+ public static int getInt(byte[] target, int offset) {
+ return Integer.reverseBytes(UNSAFE.getInt(target,
BYTE_ARRAY_BASE_OFFSET + offset));
+ }
+
+ public static void putInt(byte[] target, int offset, int value) {
+ UNSAFE.putInt(target, BYTE_ARRAY_BASE_OFFSET + offset,
Integer.reverseBytes(value));
+ }
+
+ public static long getLong(byte[] target, int offset) {
+ return Long.reverseBytes(UNSAFE.getLong(target, BYTE_ARRAY_BASE_OFFSET
+ offset));
+ }
+
+ public static void putLong(byte[] target, int offset, long value) {
+ UNSAFE.putLong(target, BYTE_ARRAY_BASE_OFFSET + offset,
Long.reverseBytes(value));
+ }
+
+ public static float getFloat(byte[] target, int offset) {
+ return Float.intBitsToFloat(Integer.reverseBytes(UNSAFE.getInt(target,
BYTE_ARRAY_BASE_OFFSET + offset)));
+ }
+
+ public static void putFloat(byte[] target, int offset, float value) {
+ UNSAFE.putInt(target, BYTE_ARRAY_BASE_OFFSET + offset,
Integer.reverseBytes(Float.floatToIntBits(value)));
+ }
+
+ public static double getDouble(byte[] target, int offset) {
+ return
Double.longBitsToDouble(Long.reverseBytes(UNSAFE.getLong(target,
BYTE_ARRAY_BASE_OFFSET + offset)));
+ }
+
+ public static void putDouble(byte[] target, int offset, double value) {
+ UNSAFE.putLong(target, BYTE_ARRAY_BASE_OFFSET + offset,
Long.reverseBytes(Double.doubleToLongBits(value)));
+ }
+}
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17421
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Icd8f8862ce03553ce2a3b6f8e1a8131bb2b78761
Gerrit-Change-Number: 17421
Gerrit-PatchSet: 1
Gerrit-Owner: Wail Alkowaileet <[email protected]>
Gerrit-MessageType: newchange