improve tuple performance tester for more types and add serialization check in TupleTest

This commit is contained in:
Alec Grieser 2019-02-24 20:49:10 -08:00
parent 78ff3d92c1
commit e6ce0ebd27
No known key found for this signature in database
GPG Key ID: CAF63551C60D3462
2 changed files with 162 additions and 12 deletions

View File

@ -13,30 +13,40 @@ import com.apple.foundationdb.tuple.Versionstamp;
public class TuplePerformanceTest {
private enum GeneratedTypes {
ALL,
LONG,
FLOATING_POINT
}
private final Random r;
private final int ignoreIterations;
private final int iterations;
private final GeneratedTypes generatedTypes;
public TuplePerformanceTest(Random r, int ignoreIterations, int iterations) {
public TuplePerformanceTest(Random r, int ignoreIterations, int iterations, GeneratedTypes generatedTypes) {
this.r = r;
this.ignoreIterations = ignoreIterations;
this.iterations = iterations;
this.generatedTypes = generatedTypes;
}
public Tuple createTuple(int length) {
public Tuple createMultiTypeTuple(int length) {
List<Object> values = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
for(int i = 0; i < length; i++) {
double choice = r.nextDouble();
if (choice < 0.1) {
if(choice < 0.1) {
values.add(null);
} else if (choice < 0.2) {
}
else if(choice < 0.2) {
byte[] bytes = new byte[r.nextInt(20)];
r.nextBytes(bytes);
values.add(bytes);
} else if (choice < 0.3) {
}
else if(choice < 0.3) {
char[] chars = new char[r.nextInt(20)];
for (int j = 0; j < chars.length; j++) {
chars[j] = (char)('a' + r.nextInt(26));
chars[j] = (char) ('a' + r.nextInt(26));
}
values.add(new String(chars));
}
@ -67,7 +77,55 @@ public class TuplePerformanceTest {
values.add(nested);
}
}
return Tuple.from(values);
return Tuple.fromItems(values);
}
public Tuple createLongsTuple(int length) {
List<Object> values = new ArrayList<>(length);
for(int i = 0; i < length; i++) {
int byteLength = r.nextInt(Long.BYTES + 1);
long val = 0L;
for(int x = 0; x < byteLength; x++) {
int nextBytes = r.nextInt(256);
val = (val << 8) + nextBytes;
}
values.add(val);
}
return Tuple.fromItems(values);
}
public Tuple createFloatingPointTuple(int length) {
List<Object> values = new ArrayList<>(length);
for(int i = 0; i < length; i++) {
double choice = r.nextDouble();
if(choice < 0.40) {
values.add(r.nextFloat());
}
else if(choice < 0.80) {
values.add(r.nextDouble());
}
// These last two are more likely to produce NaN values
else if(choice < 0.90) {
values.add(Float.intBitsToFloat(r.nextInt()));
}
else {
values.add(Double.longBitsToDouble(r.nextLong()));
}
}
return Tuple.fromItems(values);
}
public Tuple createTuple(int length) {
switch (generatedTypes) {
case ALL:
return createMultiTypeTuple(length);
case LONG:
return createLongsTuple(length);
case FLOATING_POINT:
return createFloatingPointTuple(length);
default:
throw new IllegalStateException("unknown generated types " + generatedTypes);
}
}
public void run() {
@ -169,7 +227,7 @@ public class TuplePerformanceTest {
}
public static void main(String[] args) {
TuplePerformanceTest tester = new TuplePerformanceTest(new Random(), 100_000, 10_000_000);
TuplePerformanceTest tester = new TuplePerformanceTest(new Random(), 100_000, 10_000_000, GeneratedTypes.ALL);
tester.run();
}
}

View File

@ -20,24 +20,116 @@
package com.apple.foundationdb.test;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.TransactionContext;
import com.apple.foundationdb.tuple.ByteArrayUtil;
import com.apple.foundationdb.tuple.Tuple;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class TupleTest {
private static final byte FF = (byte)0xff;
public static void main(String[] args) throws InterruptedException {
final int reps = 1000;
try {
FDB fdb = FDB.selectAPIVersion(610);
// FDB fdb = FDB.selectAPIVersion(610);
serializedForms();
/*
try(Database db = fdb.open()) {
runTests(reps, db);
}
*/
} catch(Throwable t) {
t.printStackTrace();
}
}
private static class TupleSerialization {
private final Tuple tuple;
private final byte[] serialization;
TupleSerialization(Tuple tuple, byte[] serialization) {
this.tuple = tuple;
this.serialization = serialization;
}
static void addAll(List<TupleSerialization> list, Object... args) {
for(int i = 0; i < args.length; i += 2) {
TupleSerialization serialization = new TupleSerialization((Tuple)args[i], (byte[])args[i + 1]);
list.add(serialization);
}
}
}
private static void serializedForms() {
List<TupleSerialization> serializations = new ArrayList<>();
TupleSerialization.addAll(serializations,
Tuple.from(0L), new byte[]{0x14},
Tuple.from(BigInteger.ZERO), new byte[]{0x14},
Tuple.from(1L), new byte[]{0x15, 0x01},
Tuple.from(BigInteger.ONE), new byte[]{0x15, 0x01},
Tuple.from(-1L), new byte[]{0x13, FF - 1},
Tuple.from(BigInteger.ONE.negate()), new byte[]{0x13, FF - 1},
Tuple.from(255L), new byte[]{0x15, FF},
Tuple.from(BigInteger.valueOf(255)), new byte[]{0x15, FF},
Tuple.from(-255L), new byte[]{0x13, 0x00},
Tuple.from(BigInteger.valueOf(-255)), new byte[]{0x13, 0x00},
Tuple.from(256L), new byte[]{0x16, 0x01, 0x00},
Tuple.from(BigInteger.valueOf(256)), new byte[]{0x16, 0x01, 0x00},
Tuple.from(-256L), new byte[]{0x12, FF - 1, FF},
Tuple.from(BigInteger.valueOf(-256)), new byte[]{0x12, FF - 1, FF},
Tuple.from(65536), new byte[]{0x17, 0x01, 0x00, 0x00},
Tuple.from(-65536), new byte[]{0x11, FF - 1, FF, FF},
Tuple.from(Long.MAX_VALUE), new byte[]{0x1C, 0x7f, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(BigInteger.valueOf(Long.MAX_VALUE)), new byte[]{0x1C, 0x7f, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE)), new byte[]{0x1C, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE)), new byte[]{0x1C, FF, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(BigInteger.ONE.shiftLeft(64)), new byte[]{0x1D, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(-((1L << 32) - 1)), new byte[]{0x10, 0x00, 0x00, 0x00, 0x00},
Tuple.from(BigInteger.ONE.shiftLeft(32).subtract(BigInteger.ONE).negate()), new byte[]{0x10, 0x00, 0x00, 0x00, 0x00},
Tuple.from(Long.MIN_VALUE + 2), new byte[]{0x0C, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
Tuple.from(Long.MIN_VALUE + 1), new byte[]{0x0C, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(BigInteger.valueOf(Long.MIN_VALUE).add(BigInteger.ONE)), new byte[]{0x0C, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(Long.MIN_VALUE), new byte[]{0x0C, 0x7f, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(BigInteger.valueOf(Long.MIN_VALUE)), new byte[]{0x0C, 0x7f, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE)), new byte[]{0x0C, 0x7f, FF, FF, FF, FF, FF, FF, FF - 1},
Tuple.from(BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE).negate()), new byte[]{0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(3.14f), new byte[]{0x20, (byte)0xc0, 0x48, (byte)0xf5, (byte)0xc3},
Tuple.from(-3.14f), new byte[]{0x20, (byte)0x3f, (byte)0xb7, (byte)0x0a, (byte)0x3c},
Tuple.from(3.14), new byte[]{0x21, (byte)0xc0, (byte)0x09, (byte)0x1e, (byte)0xb8, (byte)0x51, (byte)0xeb, (byte)0x85, (byte)0x1f},
Tuple.from(-3.14), new byte[]{0x21, (byte)0x3f, (byte)0xf6, (byte)0xe1, (byte)0x47, (byte)0xae, (byte)0x14, (byte)0x7a, (byte)0xe0},
Tuple.from(0.0f), new byte[]{0x20, (byte)0x80, 0x00, 0x00, 0x00},
Tuple.from(-0.0f), new byte[]{0x20, 0x7f, FF, FF, FF},
Tuple.from(0.0), new byte[]{0x21, (byte)0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(-0.0), new byte[]{0x21, 0x7f, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(Float.POSITIVE_INFINITY), new byte[]{0x20, FF, (byte)0x80, 0x00, 0x00},
Tuple.from(Float.NEGATIVE_INFINITY), new byte[]{0x20, 0x00, 0x7f, FF, FF},
Tuple.from(Double.POSITIVE_INFINITY), new byte[]{0x21, FF, (byte)0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Tuple.from(Double.NEGATIVE_INFINITY), new byte[]{0x21, 0x00, 0x0f, FF, FF, FF, FF, FF, FF},
Tuple.from(Float.intBitsToFloat(Integer.MAX_VALUE)), new byte[]{0x20, FF, FF, FF, FF},
Tuple.from(Double.longBitsToDouble(Long.MAX_VALUE)), new byte[]{0x21, FF, FF, FF, FF, FF, FF, FF, FF},
Tuple.from(Float.intBitsToFloat(~0)), new byte[]{0x20, 0x00, 0x00, 0x00, 0x00},
Tuple.from(Double.longBitsToDouble(~0L)), new byte[]{0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
);
for(TupleSerialization serialization : serializations) {
System.out.println("Packing " + serialization.tuple + " (expecting: " + ByteArrayUtil.printable(serialization.serialization) + ")");
if(!Arrays.equals(serialization.tuple.pack(), serialization.serialization)) {
throw new RuntimeException("Tuple " + serialization.tuple + " has serialization " + ByteArrayUtil.printable(serialization.tuple.pack()) +
" which does not match expected serialization " + ByteArrayUtil.printable(serialization.serialization));
}
if(!Objects.equals(serialization.tuple, Tuple.fromBytes(serialization.serialization))) {
throw new RuntimeException("Tuple " + serialization.tuple + " does not match deserialization " + Tuple.fromBytes(serialization.serialization) +
" which comes from serialization " + ByteArrayUtil.printable(serialization.serialization));
}
}
System.out.println("All tuples had matching serializations");
}
private static void runTests(final int reps, TransactionContext db) {
System.out.println("Running tests...");
long start = System.currentTimeMillis();