added benchmark subproject
This commit is contained in:
@@ -7,6 +7,7 @@ import net.woggioni.worth.antlr.JSONLexer;
|
|||||||
import net.woggioni.worth.antlr.JSONListenerImpl;
|
import net.woggioni.worth.antlr.JSONListenerImpl;
|
||||||
import net.woggioni.worth.serialization.binary.JBONDumper;
|
import net.woggioni.worth.serialization.binary.JBONDumper;
|
||||||
import net.woggioni.worth.serialization.binary.JBONParser;
|
import net.woggioni.worth.serialization.binary.JBONParser;
|
||||||
|
import net.woggioni.worth.utils.Chronometer;
|
||||||
import net.woggioni.worth.value.ObjectValue;
|
import net.woggioni.worth.value.ObjectValue;
|
||||||
import net.woggioni.worth.xface.Dumper;
|
import net.woggioni.worth.xface.Dumper;
|
||||||
import net.woggioni.worth.xface.Parser;
|
import net.woggioni.worth.xface.Parser;
|
||||||
|
176
benchmark/src/main/java/net/woggioni/worth/benchmark/Main.java
Normal file
176
benchmark/src/main/java/net/woggioni/worth/benchmark/Main.java
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package net.woggioni.worth.benchmark;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import net.woggioni.worth.antlr.JSONLexer;
|
||||||
|
import net.woggioni.worth.antlr.JSONListenerImpl;
|
||||||
|
import net.woggioni.worth.serialization.binary.JBONParser;
|
||||||
|
import net.woggioni.worth.serialization.json.JSONParser;
|
||||||
|
import net.woggioni.worth.utils.Chronometer;
|
||||||
|
import net.woggioni.worth.value.ObjectValue;
|
||||||
|
import net.woggioni.worth.xface.Value;
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static InputStream extractTestData() {
|
||||||
|
return new XZInputStream(new BufferedInputStream(Main.class.getResourceAsStream("/citylots.json.xz")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static InputStream extractBinaryTestData() {
|
||||||
|
return new XZInputStream(new BufferedInputStream(Main.class.getResourceAsStream("/citylots.jbon.xz")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream smallTestData() {
|
||||||
|
return new BufferedInputStream(Main.class.getResourceAsStream("/wordpress.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static void loopBenchmark() {
|
||||||
|
double jacksonTime, worthTime, antlrTime;
|
||||||
|
final int loops = 100;
|
||||||
|
Chronometer chr = new Chronometer();
|
||||||
|
{
|
||||||
|
ObjectMapper om = new ObjectMapper();
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
chr.reset();
|
||||||
|
for (int i = 0; i < loops; i++) {
|
||||||
|
JsonNode jsonNode = om.readTree(smallTestData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jacksonTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
||||||
|
System.out.printf("Jackson time: %8s msec\n", String.format("%.3f", jacksonTime));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
chr.reset();
|
||||||
|
for (int i = 0; i < loops; i++) {
|
||||||
|
Value value = new JSONParser().parse(smallTestData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
||||||
|
System.out.printf("Worth time: %8s msec\n", String.format("%.3f", worthTime));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
chr.reset();
|
||||||
|
for (int i = 0; i < loops; i++) {
|
||||||
|
CharStream inputStream = CharStreams.fromReader(new InputStreamReader(smallTestData()));
|
||||||
|
JSONLexer lexer = new JSONLexer(inputStream);
|
||||||
|
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
|
||||||
|
net.woggioni.worth.antlr.JSONParser parser = new net.woggioni.worth.antlr.JSONParser(commonTokenStream);
|
||||||
|
JSONListenerImpl listener = new JSONListenerImpl();
|
||||||
|
ParseTreeWalker walker = new ParseTreeWalker();
|
||||||
|
walker.walk(listener, parser.json());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
antlrTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
|
||||||
|
System.out.printf("Antlr time: %8s msec\n", String.format("%.3f", antlrTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Value.Configuration buildConfiguration() {
|
||||||
|
return Value.Configuration.builder()
|
||||||
|
.objectValueImplementation(ObjectValue.Implementation.ArrayList)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void jacksonBenchmark() {
|
||||||
|
Chronometer chr = new Chronometer();
|
||||||
|
try (InputStream is = extractTestData()) {
|
||||||
|
chr.reset();
|
||||||
|
ObjectMapper om = new ObjectMapper();
|
||||||
|
om.readTree(is);
|
||||||
|
double elapsedTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||||
|
System.out.printf("Jackson time: %8s sec\n", String.format("%.3f", elapsedTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void worthJsonBenchmark() {
|
||||||
|
Chronometer chr = new Chronometer();
|
||||||
|
try (InputStream is = extractTestData()) {
|
||||||
|
chr.reset();
|
||||||
|
new JSONParser(buildConfiguration()).parse(is);
|
||||||
|
double elapsedTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||||
|
System.out.printf("Worth json time: %8s sec\n", String.format("%.3f", elapsedTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void worthJbonBenchmark() {
|
||||||
|
Chronometer chr = new Chronometer();
|
||||||
|
try (InputStream is = extractBinaryTestData()) {
|
||||||
|
chr.reset();
|
||||||
|
new JBONParser(buildConfiguration()).parse(is);
|
||||||
|
double elapsedTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||||
|
System.out.printf("Worth jbon time: %8s sec\n", String.format("%.3f", elapsedTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void antlrBenchmark() {
|
||||||
|
Chronometer chr = new Chronometer();
|
||||||
|
try (InputStream is = extractTestData()) {
|
||||||
|
chr.reset();
|
||||||
|
CharStream inputStream = CharStreams.fromReader(new InputStreamReader(is));
|
||||||
|
JSONLexer lexer = new JSONLexer(inputStream);
|
||||||
|
CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
|
||||||
|
net.woggioni.worth.antlr.JSONParser parser = new net.woggioni.worth.antlr.JSONParser(commonTokenStream);
|
||||||
|
JSONListenerImpl listener = new JSONListenerImpl();
|
||||||
|
ParseTreeWalker walker = new ParseTreeWalker();
|
||||||
|
walker.walk(listener, parser.json());
|
||||||
|
double elapsedTime = chr.stop(Chronometer.TimeUnit.SECOND);
|
||||||
|
System.out.printf("Antlr time: %8s sec\n", String.format("%.3f", elapsedTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if(args.length == 0) {
|
||||||
|
System.out.println("Benchmark names expected as command line arguments");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
Method[] methods = Main.class.getMethods();
|
||||||
|
for(String benchmarkName : args) {
|
||||||
|
Optional<Method> targetMethod = Arrays.stream(methods)
|
||||||
|
.filter(method -> Objects.equals(benchmarkName, method.getName()))
|
||||||
|
.findFirst();
|
||||||
|
targetMethod.ifPresent(new Consumer<>() {
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public void accept(Method method) {
|
||||||
|
method.invoke(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
targetMethod.orElseThrow(() -> {
|
||||||
|
List<String> benchmarkNames = Arrays.stream(methods)
|
||||||
|
.filter(m -> m.getName()
|
||||||
|
.endsWith("Benchmark"))
|
||||||
|
.map(Method::getName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
String msg = "Unknown benchmark '" + benchmarkName +
|
||||||
|
"', available benchmarks are: " +
|
||||||
|
String.join(", ", benchmarkNames);
|
||||||
|
return new IllegalArgumentException(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
build.sbt
27
build.sbt
@@ -15,7 +15,6 @@ scalacOptions ++= Seq(
|
|||||||
)
|
)
|
||||||
|
|
||||||
git.useGitDescribe := true
|
git.useGitDescribe := true
|
||||||
fork := true
|
|
||||||
//javaOptions in Test += "-Xmx14G"
|
//javaOptions in Test += "-Xmx14G"
|
||||||
//scalafmtOnCompile := true
|
//scalafmtOnCompile := true
|
||||||
libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % Provided
|
libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % Provided
|
||||||
@@ -36,10 +35,13 @@ lazy val worthAntlr = (project in file("antlr")).settings(
|
|||||||
antlr4PackageName in Antlr4 := Some("net.woggioni.worth.antlr"),
|
antlr4PackageName in Antlr4 := Some("net.woggioni.worth.antlr"),
|
||||||
skip in publish := true,
|
skip in publish := true,
|
||||||
unmanagedClasspath in Test += (classDirectory in (LocalRootProject, Test)).value,
|
unmanagedClasspath in Test += (classDirectory in (LocalRootProject, Test)).value,
|
||||||
|
unmanagedClasspath in Runtime += (resourceDirectory in (LocalRootProject, Test)).value,
|
||||||
|
libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.6" % Test,
|
||||||
|
libraryDependencies += "org.tukaani" % "xz" % "1.8" % Test,
|
||||||
libraryDependencies += "org.antlr" % "antlr4" % antlrVersion % Test,
|
libraryDependencies += "org.antlr" % "antlr4" % antlrVersion % Test,
|
||||||
libraryDependencies += "org.antlr" % "antlr4-runtime" % antlrVersion % Test,
|
libraryDependencies += "org.antlr" % "antlr4-runtime" % antlrVersion % Test,
|
||||||
|
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test,
|
||||||
libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % Provided,
|
libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % Provided,
|
||||||
libraryDependencies ++= testDependencies
|
|
||||||
).dependsOn(LocalRootProject).enablePlugins(Antlr4Plugin)
|
).dependsOn(LocalRootProject).enablePlugins(Antlr4Plugin)
|
||||||
|
|
||||||
lazy val cli = (project in file("cli")).settings(
|
lazy val cli = (project in file("cli")).settings(
|
||||||
@@ -52,4 +54,23 @@ lazy val cli = (project in file("cli")).settings(
|
|||||||
maintainer := "oggioni.walter@gmail.com",
|
maintainer := "oggioni.walter@gmail.com",
|
||||||
unmanagedClasspath in Test += (classDirectory in (LocalRootProject, Test)).value,
|
unmanagedClasspath in Test += (classDirectory in (LocalRootProject, Test)).value,
|
||||||
libraryDependencies += "com.beust" % "jcommander" % "1.72"
|
libraryDependencies += "com.beust" % "jcommander" % "1.72"
|
||||||
).dependsOn(LocalRootProject).enablePlugins(JavaAppPackaging).enablePlugins(UniversalPlugin)
|
).dependsOn(LocalRootProject).enablePlugins(JavaAppPackaging).enablePlugins(UniversalPlugin)
|
||||||
|
|
||||||
|
lazy val benchmark = (project in file("benchmark")).settings(
|
||||||
|
organization := (organization in LocalRootProject).value,
|
||||||
|
name := "worth-benchmark",
|
||||||
|
version := (version in LocalRootProject).value,
|
||||||
|
resourceDirectory in Compile := (resourceDirectory in(LocalRootProject, Test)).value,
|
||||||
|
skip in publish := true,
|
||||||
|
maintainer := "oggioni.walter@gmail.com",
|
||||||
|
mainClass := Some("net.woggioni.worth.benchmark.Main"),
|
||||||
|
javaOptions in Universal += "-J-Xmx4G",
|
||||||
|
fork := true,
|
||||||
|
libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.6",
|
||||||
|
libraryDependencies += "org.tukaani" % "xz" % "1.8",
|
||||||
|
libraryDependencies += "com.beust" % "jcommander" % "1.72",
|
||||||
|
libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % Provided
|
||||||
|
).dependsOn(LocalRootProject)
|
||||||
|
.dependsOn(worthAntlr)
|
||||||
|
.enablePlugins(JavaAppPackaging)
|
||||||
|
.enablePlugins(UniversalPlugin)
|
||||||
|
@@ -218,9 +218,9 @@ public class JSONParser extends ValueParser {
|
|||||||
try {
|
try {
|
||||||
String text = parseNumber(stream);
|
String text = parseNumber(stream);
|
||||||
if (text.indexOf('.') > 0) {
|
if (text.indexOf('.') > 0) {
|
||||||
floatValue(Double.valueOf(text));
|
floatValue(Double.parseDouble(text));
|
||||||
} else {
|
} else {
|
||||||
integerValue(Long.valueOf(text));
|
integerValue(Long.parseLong(text));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package net.woggioni.worth.serialization.json;
|
package net.woggioni.worth.utils;
|
||||||
|
|
||||||
public class Chronometer {
|
public class Chronometer {
|
||||||
|
|
@@ -199,7 +199,7 @@ class ListObjectValue implements ObjectValue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(String key, Value value2Put) {
|
public void put(String key, Value value2Put) {
|
||||||
value.add(new ObjectEntry(key, value2Put));
|
value.add(new ObjectEntry<>(key, value2Put));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -97,10 +97,6 @@ public interface Value {
|
|||||||
public final ObjectValue.Implementation objectValueImplementation = ObjectValue.Implementation.valueOf(
|
public final ObjectValue.Implementation objectValueImplementation = ObjectValue.Implementation.valueOf(
|
||||||
System.getProperty(ObjectValue.class.getName() + ".implementation", "TreeMap"));
|
System.getProperty(ObjectValue.class.getName() + ".implementation", "TreeMap"));
|
||||||
|
|
||||||
@Builder.Default
|
|
||||||
public final boolean useReferences = Boolean.valueOf(
|
|
||||||
System.getProperty(Value.class.getName() + ".useReferences", "false"));
|
|
||||||
|
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
public final int maxDepth =
|
public final int maxDepth =
|
||||||
Integer.parseInt(System.getProperty(Value.class.getName() + ".maxDepth", "1048576"));
|
Integer.parseInt(System.getProperty(Value.class.getName() + ".maxDepth", "1048576"));
|
||||||
|
Reference in New Issue
Block a user