package water;
import org.junit.*;
import java.util.ArrayList;
import jsr166y.ForkJoinTask;
import jsr166y.RecursiveAction;
import water.util.PrettyPrint;
@Ignore("Speed/perf test, not intended as a pre-push junit test")
public class KVSpeedTest extends TestUtil {
static final int NCLOUD=5;
static final int NKEYS=1000000;
@BeforeClass static public void setup() { stall_till_cloudsize(1); }
// Make a million keys-per-node. Make sure they are all cached/shared on at
// least one other node. Time removing them all. Can be network bound as
// the million read/write/put/invalidates hit the wires.
@Test @Ignore
public void testMillionRemoveKeys() {
long start = System.currentTimeMillis();
// Compute home keys
byte[] homes = new byte[NKEYS*NCLOUD];
for( int i=0; i<homes.length; i++ )
homes[i] = (byte)Key.make("Q"+i).home(H2O.CLOUD);
final Key k = Key.make("homes");
DKV.put(k,new Value(k,homes));
start = logTime(start,"HOMEALL",NCLOUD);
// Populate NKEYS locally
new MRTask() {
@Override protected void setupLocal() {
byte[] homes = DKV.get(k).rawMem();
final int sidx = H2O.SELF.index();
long start = System.currentTimeMillis();
for( int i=0; i<homes.length; i++ ) {
if( homes[i]==sidx ) {
String s = "Q"+i;
Key k = Key.make(s);
DKV.put(k,new Value(k,s),_fs);
}
}
logTime(start, "PUT1 "+H2O.SELF, 1);
}
}.doAllNodes();
start = logTime(start,"PUTALL",NCLOUD);
// Force sharing at least once
new MRTask() {
@Override protected void setupLocal() {
byte[] homes = DKV.get(k).rawMem();
final int sidx = H2O.SELF.index();
long start = System.currentTimeMillis();
for( int i=0; i<homes.length; i++ )
if( homes[i]==sidx )
DKV.prefetch(Key.make("Q"+i+1));
start = logTime(start, "PREFETCH1 "+H2O.SELF, 1);
for( int i=0; i<homes.length; i++ )
if( homes[i]==sidx )
DKV.get(Key.make("Q"+i+1));
logTime(start, "GET1 "+H2O.SELF, 1);
}
}.doAllNodes();
start = logTime(start,"GETALL",NCLOUD);
Futures fs = new Futures();
for( int i=0; i<homes.length; i++ )
DKV.remove(Key.make("Q"+i), fs);
start = logTime(start,"REMALL_START",NCLOUD);
fs.blockForPending();
logTime(start,"REMALL_DONE",NCLOUD);
DKV.remove(k);
System.out.printf("STORE size = "+H2O.STORE.size());
System.out.printf("STORE raw array length = "+H2O.STORE.raw_array().length);
}
@Test @Ignore
public void testMillionInsertKeys() {
final int PAR=100;
final int NKEY=100000; // PAR*NKEY = 100M keys
final int WARMKEY=10000; // PAR*WARMKEY = 1M keys
H2O.H2OCountedCompleter foo = H2O.submitTask(new H2O.H2OCountedCompleter() {
final Key [][] keys = new Key [PAR][NKEY];
final Value[][] vals = new Value[PAR][NKEY];
@Override public void compute2() {
long now, start = System.currentTimeMillis();
ArrayList<RecursiveAction> rs = new ArrayList<>();
// Make a zillion keys
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.add(new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < NKEY; j++ )
keys[fi][j] = Key.make("Q"+(fi*NKEY+j));
}
});
}
ForkJoinTask.invokeAll(rs);
now = System.currentTimeMillis();
System.out.println("create msec="+(now-start)+", msec/op="+((double)(now-start))/PAR/NKEY);
start = now;
// Warmup hashmap
for( int X=0; X<4; X++ ) {
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.add(new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < WARMKEY; j++ ) {
Key k = keys[fi][j];
H2O.putIfMatch(k, vals[fi][j] = new Value(k, ""), null);
}
}
});
}
ForkJoinTask.invokeAll(rs);
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.set(fi,new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < WARMKEY; j++ )
H2O.putIfMatch(keys[fi][j], null, vals[fi][j]);
}
});
}
ForkJoinTask.invokeAll(rs);
now = System.currentTimeMillis();
System.out.println("warmup msec="+(now-start)+", msec/op="+((double)(now-start))/PAR/WARMKEY);
try { Thread.sleep(1000); } catch( InterruptedException ie ) {}
start = System.currentTimeMillis();
}
System.out.println("Starting insert work");
// Make a zillion Values in parallel
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.add(new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < NKEY; j++ )
vals[fi][j] = new Value(keys[fi][j], "");
}
});
}
ForkJoinTask.invokeAll(rs);
now = System.currentTimeMillis();
System.out.println("Values msec="+(now-start)+", msec/op="+((double)(now-start))/PAR/NKEY);
start = now;
// Insert a zillion keys in parallel
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.add(new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < NKEY; j++ ) {
Key k = keys[fi][j];
H2O.putIfMatch(k, vals[fi][j], null);
}
}
});
}
ForkJoinTask.invokeAll(rs);
now = System.currentTimeMillis();
System.out.println("insert msec="+(now-start)+", msec/op="+((double)(now-start))/PAR/NKEY);
start = now;
// Now remove them all
for( int i = 0; i < PAR; ++i ) {
final int fi = i;
rs.set(fi,new RecursiveAction() {
@Override public void compute() { // Make & insert Keys in parallel
for( int j = 0; j < NKEY; j++ )
H2O.putIfMatch(keys[fi][j], null, vals[fi][j]);
}
});
}
ForkJoinTask.invokeAll(rs);
now = System.currentTimeMillis();
System.out.println("remove msec="+(now-start)+", msec/op="+((double)(now-start))/PAR/NKEY);
start = now;
tryComplete();
}
});
foo.join();
System.out.printf("STORE size = %d\n",H2O.STORE.size());
System.out.printf("STORE raw array length = %d\n",H2O.STORE.raw_array().length);
}
private long logTime( long start, String msg, int ncloud ) {
long now = System.currentTimeMillis();
double msec_op = (double)(now-start)/NKEYS/ncloud;
System.out.println(msg+" "+ PrettyPrint.usecs((long)(msec_op*1000.0))+"/op");
return now;
}
}