2019-03-07 11:41:45 +01:00
|
|
|
package it.cavallium.strangedb.tests;
|
2019-03-02 17:47:24 +01:00
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
import it.cavallium.strangedb.annotations.*;
|
|
|
|
import it.cavallium.strangedb.functionalinterfaces.RunnableWithIO;
|
|
|
|
import it.cavallium.strangedb.lists.EnhancedObjectStrandeDbList;
|
|
|
|
import it.cavallium.strangedb.lists.ObjectStrandeDbList;
|
2019-03-02 17:47:24 +01:00
|
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
2019-03-07 11:41:45 +01:00
|
|
|
import it.cavallium.strangedb.database.Database;
|
|
|
|
import it.cavallium.strangedb.EnhancedObject;
|
|
|
|
import it.cavallium.strangedb.database.IDatabaseTools;
|
|
|
|
import it.cavallium.strangedb.VariableWrapper;
|
2019-03-02 17:47:24 +01:00
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.nio.file.Path;
|
2019-03-06 21:21:28 +01:00
|
|
|
import java.nio.file.Paths;
|
2019-03-02 17:47:24 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
public class Performance {
|
|
|
|
private static boolean FAST_TESTS;
|
|
|
|
|
|
|
|
private static Path rootDirectory;
|
|
|
|
private static Path dbDataFile;
|
|
|
|
private static Path dbBlocksFile;
|
|
|
|
private static Path dbReferencesFile;
|
|
|
|
private static Database db;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param args args[0] = true for fast tests
|
|
|
|
* @throws IOException
|
|
|
|
* @throws InterruptedException
|
|
|
|
*/
|
|
|
|
public static void main(String[] args) throws IOException, InterruptedException {
|
|
|
|
FAST_TESTS = args.length > 0 && args[0].equalsIgnoreCase("true");
|
2019-03-06 21:21:28 +01:00
|
|
|
if (args.length >= 2) {
|
|
|
|
rootDirectory = Paths.get(args[1]);
|
|
|
|
try {
|
|
|
|
Files.createDirectory(rootDirectory);
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rootDirectory = Files.createTempDirectory("performance-tests");
|
|
|
|
}
|
2019-03-02 17:47:24 +01:00
|
|
|
generateDb();
|
|
|
|
System.out.println("Performance test started.");
|
|
|
|
System.out.println("-------------------------------------------------------+-----------------------------------------------------------------");
|
|
|
|
System.out.println("Test name Total Time | Time at 1 Time at 10 Time at 100 Time at 1K Time at 10K");
|
|
|
|
System.out.println("-------------------------------------------------------+-----------------------------------------------------------------");
|
|
|
|
testS("Database creation", 3000, Performance::deleteDb, Performance::generateDb, () -> {});
|
|
|
|
testS("Database root creation", 3000, Performance::regenDb, () -> db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new), () -> {});
|
|
|
|
final VariableWrapper<PreloadedListContainer> preloadedListContainer = new VariableWrapper<>(null);
|
|
|
|
final VariableWrapper<SimpleEnhancedObject> simpleEnhancedObjectContainer = new VariableWrapper<>(null);
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int> creation", 3000, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
}, () -> preloadedListContainer.var.list = new ObjectStrandeDbList<>(db), () -> {});
|
|
|
|
testS("ObjectStrandeDbList<Int>: Filling with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<EnhancedObject>: Filling with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class);
|
2019-03-02 17:47:24 +01:00
|
|
|
simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db);
|
|
|
|
simpleEnhancedObjectContainer.var.integerNumber = 10;
|
|
|
|
simpleEnhancedObjectContainer.var.longNumber = 10L;
|
|
|
|
simpleEnhancedObjectContainer.var.object = new ArrayList<>();
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv");
|
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: Filling with 10000 items", 10, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: Filling with 100000 items", 1, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 100000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: Loading 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.list.get(i);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<EnhancedObject>: Loading with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class);
|
2019-03-02 17:47:24 +01:00
|
|
|
simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db);
|
|
|
|
simpleEnhancedObjectContainer.var.integerNumber = 10;
|
|
|
|
simpleEnhancedObjectContainer.var.longNumber = 10L;
|
|
|
|
simpleEnhancedObjectContainer.var.object = new ArrayList<>();
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv");
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.listOfEnhancedObj.get(i);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: Loading 10000 items", 10, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
|
|
preloadedListContainer.var.list.get(i);
|
|
|
|
}
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: getLast() with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
preloadedListContainer.var.list.getLast();
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<EnhancedObject>: getLast() with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.listOfEnhancedObj = new EnhancedObjectStrandeDbList<>(db, SimpleEnhancedObject.class);
|
2019-03-02 17:47:24 +01:00
|
|
|
simpleEnhancedObjectContainer.var = new SimpleEnhancedObject(db);
|
|
|
|
simpleEnhancedObjectContainer.var.integerNumber = 10;
|
|
|
|
simpleEnhancedObjectContainer.var.longNumber = 10L;
|
|
|
|
simpleEnhancedObjectContainer.var.object = new ArrayList<>();
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XHIghicuiHUCB UIVY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("ioZ>UIHZXGHXYGY");
|
|
|
|
simpleEnhancedObjectContainer.var.object.add("XJIOUIhcgGuigscwvyv");
|
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.listOfEnhancedObj.add(simpleEnhancedObjectContainer.var);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
preloadedListContainer.var.listOfEnhancedObj.getLast();
|
|
|
|
}, () -> {});
|
2019-03-07 11:41:45 +01:00
|
|
|
testS("ObjectStrandeDbList<Int>: size() with 1000 items", 100, () -> {
|
2019-03-02 17:47:24 +01:00
|
|
|
regenDb();
|
|
|
|
preloadedListContainer.var = db.loadRoot(PreloadedListContainer.class, PreloadedListContainer::new);
|
2019-03-07 11:41:45 +01:00
|
|
|
preloadedListContainer.var.list = new ObjectStrandeDbList<>(db);
|
2019-03-02 17:47:24 +01:00
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
preloadedListContainer.var.list.add(1000);
|
|
|
|
}
|
|
|
|
}, () -> {
|
|
|
|
preloadedListContainer.var.list.size();
|
|
|
|
}, () -> {});
|
|
|
|
System.out.println("-------------------------------------------------------+-----------------------------------------------------------------");
|
|
|
|
System.out.println("Performance test finished.");
|
|
|
|
deleteDb();
|
|
|
|
Files.deleteIfExists(rootDirectory);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void NtestS(String description, int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void testS(String description, int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException {
|
|
|
|
if (FAST_TESTS) {
|
|
|
|
if (times >= 5) {
|
|
|
|
times /= 5;
|
|
|
|
} else if (times >= 2) {
|
|
|
|
times /= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
description = description + " time is";
|
|
|
|
int spacesCount = 40 - description.length();
|
|
|
|
int cutAt = 0;
|
|
|
|
if (spacesCount < 0) {
|
|
|
|
spacesCount = 40 - (description.length() - 40);
|
|
|
|
cutAt = 40;
|
|
|
|
}
|
|
|
|
StringBuilder spaces = new StringBuilder();
|
|
|
|
for (int i = 0; i < spacesCount; i++) {
|
|
|
|
spaces.append(' ');
|
|
|
|
}
|
|
|
|
double[] results = test(times, beforeAction, action, afterAction);
|
|
|
|
if (cutAt > 0) {
|
|
|
|
System.out.println(description.substring(0, cutAt) + " |");
|
|
|
|
}
|
|
|
|
System.out.printf("%s:%s%s%s%n", description.substring(cutAt), spaces, format(results[0]) + " |", results.length > 1 ? (format(results[1]) + (results.length > 2 ? (format(results[2]) + (results.length > 3 ? (format(results[3]) + (results.length > 4 ? (format(results[4]) + (results.length > 5 ? format(results[5]) : "")) : "")) : "")) : "")) : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String format(double result) {
|
|
|
|
String spaces;
|
|
|
|
if (result < 10) {
|
|
|
|
spaces = " ";
|
|
|
|
} else if (result < 100) {
|
|
|
|
spaces = " ";
|
|
|
|
} else if (result < 1000) {
|
|
|
|
spaces = " ";
|
|
|
|
} else {
|
|
|
|
spaces = " ";
|
|
|
|
}
|
|
|
|
return spaces + String.format("%.2fms", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static double[] test(int times, RunnableWithIO beforeAction, RunnableWithIO action, RunnableWithIO afterAction) throws IOException, InterruptedException {
|
|
|
|
LongArrayList results = new LongArrayList(times);
|
|
|
|
Thread.sleep(100);
|
|
|
|
System.gc();
|
|
|
|
Thread.sleep(100);
|
|
|
|
for (int i = 0; i < times; i++) {
|
|
|
|
beforeAction.run();
|
|
|
|
long startTime = System.nanoTime();
|
|
|
|
action.run();
|
|
|
|
long elapsedTime = System.nanoTime() - startTime;
|
|
|
|
afterAction.run();
|
|
|
|
results.add(elapsedTime);
|
|
|
|
}
|
|
|
|
double result1 = results.stream().limit(1).mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
double result10 = results.stream().limit(10).mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
double result100 = results.stream().limit(100).mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
double result1000 = results.stream().limit(1000).mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
double result10000 = results.stream().limit(10000).mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
double resultMax = results.stream().mapToLong(val -> val).average().orElse(0.0) / 1000000d;
|
|
|
|
if (times <= 1) {
|
|
|
|
return new double[]{resultMax};
|
|
|
|
} else if (times <= 10) {
|
|
|
|
return new double[]{resultMax, result1};
|
|
|
|
} else if (times <= 100) {
|
|
|
|
return new double[]{resultMax, result1, result10};
|
|
|
|
} else if (times <= 1000) {
|
|
|
|
return new double[]{resultMax, result1, result10, result100};
|
|
|
|
} else if (times <= 10000) {
|
|
|
|
return new double[]{resultMax, result1, result10, result100, result1000};
|
|
|
|
} else {
|
|
|
|
return new double[]{resultMax, result1, result10, result100, result1000, result10000};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void generateDb() throws IOException {
|
|
|
|
dbDataFile = Files.createFile(rootDirectory.resolve("db_data.dat"));
|
|
|
|
dbBlocksFile = Files.createFile(rootDirectory.resolve("db_blocks.dat"));
|
|
|
|
dbReferencesFile = Files.createFile(rootDirectory.resolve("db_references.dat"));
|
|
|
|
db = new Database(dbDataFile, dbBlocksFile, dbReferencesFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void deleteDb() throws IOException {
|
|
|
|
db.close();
|
|
|
|
Files.deleteIfExists(dbDataFile);
|
|
|
|
Files.deleteIfExists(dbBlocksFile);
|
|
|
|
Files.deleteIfExists(dbReferencesFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void regenDb() throws IOException {
|
|
|
|
deleteDb();
|
|
|
|
generateDb();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class PreloadedListContainer extends EnhancedObject {
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbField(id = 0, type = DbDataType.ENHANCED_OBJECT)
|
|
|
|
public ObjectStrandeDbList<Integer> list;
|
2019-03-02 17:47:24 +01:00
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbField(id = 1, type = DbDataType.ENHANCED_OBJECT)
|
|
|
|
public EnhancedObjectStrandeDbList<SimpleEnhancedObject> listOfEnhancedObj;
|
2019-03-02 17:47:24 +01:00
|
|
|
|
|
|
|
public PreloadedListContainer() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public PreloadedListContainer(IDatabaseTools databaseTools) throws IOException {
|
|
|
|
super(databaseTools);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class DynamicListContainer extends EnhancedObject {
|
|
|
|
|
|
|
|
public DynamicListContainer() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public DynamicListContainer(IDatabaseTools databaseTools) throws IOException {
|
|
|
|
super(databaseTools);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbPropertyGetter(id = 0, type = DbDataType.ENHANCED_OBJECT)
|
|
|
|
public ObjectStrandeDbList<Integer> getList() {
|
2019-03-02 17:47:24 +01:00
|
|
|
return getProperty();
|
|
|
|
}
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbPropertySetter(id = 1, type = DbDataType.ENHANCED_OBJECT)
|
|
|
|
public void setList(ObjectStrandeDbList<Integer> list) {
|
2019-03-02 17:47:24 +01:00
|
|
|
setProperty(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class SimpleEnhancedObject extends EnhancedObject {
|
|
|
|
public SimpleEnhancedObject() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public SimpleEnhancedObject(IDatabaseTools databaseTools) throws IOException {
|
|
|
|
super(databaseTools);
|
|
|
|
}
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbField(id = 0, type = DbDataType.OBJECT)
|
2019-03-02 17:47:24 +01:00
|
|
|
public ArrayList<String> object;
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbPrimitiveField(id = 0, type = DbPrimitiveType.INTEGER)
|
2019-03-02 17:47:24 +01:00
|
|
|
public int integerNumber;
|
|
|
|
|
2019-03-07 11:41:45 +01:00
|
|
|
@DbPrimitiveField(id = 1, type = DbPrimitiveType.LONG)
|
2019-03-02 17:47:24 +01:00
|
|
|
public long longNumber;
|
|
|
|
}
|
|
|
|
}
|