Optimization of TableEnumerator/MultiWrite
Change-Id: Iefc6cb15d6ee2a16b288a867499d79802320df09
diff --git a/src/main/java/edu/stanford/ramcloud/JRamCloud.java b/src/main/java/edu/stanford/ramcloud/JRamCloud.java
index dfb4b6a..63b0748 100644
--- a/src/main/java/edu/stanford/ramcloud/JRamCloud.java
+++ b/src/main/java/edu/stanford/ramcloud/JRamCloud.java
@@ -14,9 +14,8 @@
*/
package edu.stanford.ramcloud;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.lang.Integer;
+import java.util.LinkedList;
/*
* This class provides Java bindings for RAMCloud. Right now it is a rather
@@ -78,31 +77,53 @@
}
}
- public static class multiReadObject {
- long tableId;
- byte[] key;
+ public static class MultiReadObject {
+ public long[] tableId;
+ public byte[] key[];
+ public short[] keyLength;
- public multiReadObject(long _tableId, byte[] _key){
- tableId = _tableId;
- key = _key;
+ public MultiReadObject(int size){
+ this.tableId = new long[size];
+ this.key = new byte[size][];
+ this.keyLength = new short[size];
}
+
+ public void setObject(int num, long tableId, byte key[]){
+ this.tableId[num] = tableId;
+ this.key[num] = key;
+ this.keyLength[num] = (short) this.key[num].length;
+ }
}
public static class MultiWriteObject {
- long tableId;
- byte[] key;
- byte[] value;
- RejectRules rules;
+ public long[] tableId;
+ public byte[] key[];
+ public short[] keyLength;
+ public byte[] value[];
+ public short[] valueLength;
+ public RejectRules[] rules;
- public MultiWriteObject(long tableId, byte[] key, byte[] value, RejectRules rules) {
- this.tableId = tableId;
- this.key = key;
- this.value = value;
- this.rules = rules;
+ public MultiWriteObject(int size) {
+ this.tableId = new long[size];
+ this.key = new byte[size][];
+ this.keyLength = new short[size];
+ this.value = new byte[size][];
+ this.valueLength = new short[size];
+ this.rules = new RejectRules[size];
}
+
+ public void setObject(int num, long tableId, byte key[], byte value[], RejectRules rules){
+ this.tableId[num] = tableId;
+ this.key[num] = key;
+ this.keyLength[num] = (short) key.length;
+ this.value[num] = value;
+ this.valueLength[num] = (short) value.length;
+ this.rules[num] = rules;
+ }
+
}
- public class MultiWriteRspObject {
+ public static class MultiWriteRspObject {
private int status;
private long version;
@@ -127,7 +148,7 @@
* or multiple return values, and we don't know the object's size ahead of
* time, so passing in a fixed-length array would be problematic.
*/
- public class Object {
+ public static class Object {
Object(byte[] _key, byte[] _value, long _version)
{
key = _key;
@@ -151,6 +172,17 @@
final public byte[] value;
final public long version;
}
+
+ public static class TableEnumeratorObject {
+ TableEnumeratorObject(Object[] _object, long _nextHash)
+ {
+ object = _object;
+ nextHash = _nextHash;
+ }
+
+ final public Object[] object;
+ final public long nextHash;
+ }
public class TableEnumerator {
private long tableEnumeratorObjectPointer = 0;
@@ -167,6 +199,43 @@
public native Object next();
}
+ public class TableEnumerator2 {
+
+ protected long tableId;
+ protected LinkedList<JRamCloud.Object> rcobjs = null;
+ protected long nextHash = 0;
+ protected boolean done = false;
+
+ public TableEnumerator2(long tableId)
+ {
+ this.tableId = tableId;
+ rcobjs = new LinkedList<>();
+ }
+ public boolean hasNext() {
+ if (rcobjs.isEmpty())
+ {
+ if (done) {
+ return false;
+ }
+ JRamCloud.TableEnumeratorObject o = getTableObjects(this.tableId, this.nextHash);
+ if (o.nextHash == 0L) {
+ done = true;
+ }
+ this.nextHash = o.nextHash;
+ rcobjs.addAll(Arrays.asList(o.object));
+ if (rcobjs.isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Object next()
+ {
+ return rcobjs.pop();
+ }
+ }
+
/**
* Connect to the RAMCloud cluster specified by the given coordinator's
* service locator string. This causes the JNI code to instantiate the
@@ -294,7 +363,8 @@
public native long write(long tableId, byte[] key, byte[] value);
public native long write(long tableId, byte[] key, byte[] value, RejectRules rules);
public native long writeRule(long tableId, byte[] key, byte[] value, RejectRules rules);
- public native MultiWriteRspObject[] multiWrite(MultiWriteObject[] mwrite);
+ public native MultiWriteRspObject[] multiWrite(long[] tableId, byte[] key[], short[] keyDataSize, byte[] value[], short[] valueDataSize, int requestNum, RejectRules[] rules);
+ public native TableEnumeratorObject getTableObjects(long tableId, long nextHash);
/*
* The following exceptions may be thrown by the JNI functions:
@@ -339,7 +409,60 @@
super(message);
}
}
+
+ public static void tableEnumeratorTest(JRamCloud ramcloud) {
+ long startTime = 0;
+ for (int x = 0 ; x < 2 ; x ++){
+ for(int N = 1000; N < 10000; N += 1000) {
+ long EnumerateTesttable = ramcloud.createTable("EnumerateTest");
+ for(int i = 0 ; i < N ; ++i) {
+ String key = new Integer(i).toString();
+ ramcloud.write(EnumerateTesttable, key.getBytes(), "Hello, World!".getBytes());
+ }
+ MultiReadObject mread[] = new MultiReadObject[N];
+ long tableIdList[] = new long[N];
+ byte[] keydata[] = new byte[N][];
+ short keydataSize[] = new short[N];
+ startTime = System.nanoTime();
+ for (int j = 0 ; j < N ; ++j) {
+ tableIdList[j] = EnumerateTesttable;
+ String key = new Integer(j).toString();
+ keydata[j] = key.getBytes();
+ keydataSize[j] = (short) keydata[j].length;
+ }
+ JRamCloud.Object out[] = ramcloud.multiRead(tableIdList, keydata, keydataSize, N);
+ for (int i = 0; i < N; ++i) {
+ if(out[i].version == 0) {
+ System.out.println("Verify fail " + out[i].getKey() + " V:" + out[i].getValue());
+ }
+ }
+
+ System.out.println("multiRead : " + N + " Time : " + (System.nanoTime()-startTime));
+
+ startTime = System.nanoTime();
+ JRamCloud.TableEnumerator tableEnum = ramcloud.new TableEnumerator(EnumerateTesttable);
+ while (tableEnum.hasNext()) {
+ Object tableEntry = tableEnum.next();
+ if (tableEntry != null) {
+ System.out.println("tableEnumerator object: key = [" + tableEntry.getKey() + "], value = [" + tableEntry.getValue() + "]");
+ }
+ }
+ System.out.println("old TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));
+
+ startTime = System.nanoTime();
+ JRamCloud.TableEnumerator2 tableEnum2 = ramcloud.new TableEnumerator2(EnumerateTesttable);
+ while (tableEnum2.hasNext()) {
+ Object tableEntry2 = tableEnum2.next();
+ if (tableEntry2 != null) {
+ System.out.println("tableEnumerator2 object: key = [" + tableEntry2.getKey() + "], value = [" + tableEntry2.getValue() + "]");
+ }
+ }
+ System.out.println("new TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));
+ ramcloud.dropTable("EnumerateTest");
+ }
+ }
+ }
/**
* A simple end-to-end test of the java bindings.
*/
@@ -391,30 +514,26 @@
ramcloud.write(tableId6, "object3-1", "value:3-1");
ramcloud.write(tableId6, "object3-2", "value:3-2");
- long tableIdList[] = new long[2];
- byte[] keydata[] = new byte[2][];
- short keydataSize[] = new short[2];
- tableIdList[0] = tableId4;
- keydata[0] = "object1-1".getBytes();
- keydataSize[0] = (short) keydata[0].length;
- tableIdList[1] = tableId5;
- keydata[1] = "object2-1".getBytes();
- keydataSize[1] = (short) keydata[1].length;
+ MultiReadObject mr = new MultiReadObject(2);
+ MultiWriteObject mw = new MultiWriteObject(2);
+
+ mr.setObject(0, tableId4, "object1-1".getBytes());
+ mr.setObject(1, tableId5, "object2-1".getBytes());
- JRamCloud.Object out[] = ramcloud.multiRead(tableIdList, keydata, keydataSize, 2);
+ JRamCloud.Object out[] = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
for (int i = 0 ; i < 2 ; i++){
System.out.println("multi read object: key = [" + out[i].getKey() + "], value = ["
+ out[i].getValue() + "]");
}
- MultiWriteObject mwrite[] = new MultiWriteObject[2];
for (int i = 0; i < 1000; i++) {
String key1 = "key1" + new Integer(i).toString();
String key2 = "key2" + new Integer(i).toString();
-
- mwrite[0] = new MultiWriteObject(tableId4, key1.getBytes(), "v0-value".getBytes(), null);
- mwrite[1] = new MultiWriteObject(tableId5, key2.getBytes(), "v1".getBytes(), null);
- MultiWriteRspObject[] rsp = ramcloud.multiWrite(mwrite);
+
+ mw.setObject(0, tableId4, key1.getBytes(), "v0-value".getBytes(), null);
+ mw.setObject(1, tableId5, key2.getBytes(), "v1".getBytes(), null);
+
+ MultiWriteRspObject[] rsp = ramcloud.multiWrite(mw.tableId, mw.key, mw.keyLength, mw.value, mw.valueLength, 2, mw.rules);
if (rsp != null) {
for (int j = 0; j < rsp.length; j++) {
System.out.println("multi write rsp(" + j + ") status:version " + rsp[j].getStatus() + ":" + rsp[j].getVersion());
@@ -424,19 +543,18 @@
for (int i = 0; i < 1000; i++) {
String key1 = "key1" + new Integer(i).toString();
String key2 = "key2" + new Integer(i).toString();
- tableIdList[0] = tableId4;
- keydata[0] = key1.getBytes();
- keydataSize[0] = (short) keydata[0].length;
- tableIdList[1] = tableId5;
- keydata[1] = key2.getBytes();
- keydataSize[1] = (short) keydata[1].length;
- out = ramcloud.multiRead(tableIdList, keydata, keydataSize, 2);
+ mr.setObject(0, tableId4, key1.getBytes());
+ mr.setObject(1, tableId5, key2.getBytes());
+
+ out = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
for (int j = 0; j < 2; j++) {
System.out.println("multi read object: key = [" + out[j].getKey() + "], value = [" + out[j].getValue() + "]");
}
}
+ tableEnumeratorTest(ramcloud);
+
ramcloud.dropTable("table4");
ramcloud.dropTable("table5");
ramcloud.dropTable("table6");