added system property to switch object value implementation

This commit is contained in:
Walter Oggioni
2019-07-16 16:56:07 +02:00
committed by Walter Oggioni
parent 7f50efb4dc
commit a2e5e669f1
13 changed files with 108 additions and 57 deletions

View File

@@ -24,7 +24,7 @@ public abstract class ValueDumper implements Dumper {
}
protected static class ArrayStackLevel extends StackLevel implements Iterator<Value> {
private final Iterator<Value> iterator = value.asArray().iterator();
private final Iterator<Value> iterator = ((ArrayValue) value).iterator();
@Override
public Value next() {
@@ -43,7 +43,7 @@ public abstract class ValueDumper implements Dumper {
}
protected static class ObjectStackLevel extends StackLevel implements Iterator<Map.Entry<String, Value>> {
private final Iterator<Map.Entry<String, Value>> iterator = value.asObject().entrySet().iterator();
private final Iterator<Map.Entry<String, Value>> iterator = ((ObjectValue) value).iterator();
@Override
public Map.Entry<String, Value> next() {

View File

@@ -4,8 +4,8 @@ import lombok.RequiredArgsConstructor;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.*;
import net.woggioni.worth.xface.Value;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;

View File

@@ -2,13 +2,13 @@ package net.woggioni.worth.serialization.binary;
import lombok.SneakyThrows;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.utils.Leb128;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Value;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Value;
import java.io.OutputStream;
import java.io.Writer;

View File

@@ -1,13 +1,13 @@
package net.woggioni.worth.serialization.binary;
import lombok.SneakyThrows;
import net.woggioni.worth.utils.Leb128;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.xface.Value;
import net.woggioni.worth.buffer.LookAheadInputStream;
import net.woggioni.worth.exception.ParseException;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.utils.Leb128;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import java.io.InputStream;
import java.util.function.Function;

View File

@@ -1,12 +1,12 @@
package net.woggioni.worth.serialization.json;
import lombok.SneakyThrows;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Value;
import net.woggioni.worth.serialization.ValueDumper;
import net.woggioni.worth.xface.Dumper;
import net.woggioni.worth.xface.Value;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

View File

@@ -1,7 +1,6 @@
package net.woggioni.worth.serialization.json;
import lombok.SneakyThrows;
import net.woggioni.worth.xface.Value;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.exception.IOException;
import net.woggioni.worth.exception.NotImplementedException;
@@ -9,6 +8,7 @@ import net.woggioni.worth.exception.ParseException;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;

View File

@@ -4,6 +4,7 @@ import lombok.EqualsAndHashCode;
import net.woggioni.worth.xface.Value;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -59,10 +60,9 @@ public class ArrayValue implements Value, Iterable<Value> {
@Override
public List<Value> asArray() {
return value;
return Collections.unmodifiableList(value);
}
@Override
public Iterator<Value> iterator() {
return value.iterator();

View File

@@ -2,29 +2,48 @@ package net.woggioni.worth.value;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.woggioni.worth.utils.WorthUtils;
import net.woggioni.worth.xface.Value;
import java.util.*;
public interface ObjectValue extends Value, Iterable<Map.Entry<String, Value>> {
boolean listBasedImplementation = Boolean.valueOf(
System.getProperty(ObjectValue.class.getName() + ".listBasedImplementation", "false"));
boolean preserveKeyOrder = Boolean.valueOf(
System.getProperty(ObjectValue.class.getName() + ".preserveKeyOrder", "false"));
Implementation implementation = Implementation.valueOf(
System.getProperty(ObjectValue.class.getName() + ".implementation", "TreeMap"));
static ObjectValue newInstance() {
if (listBasedImplementation) {
return new ListObjectValue();
} else {
return new MapObjectValue();
ObjectValue result;
switch(implementation) {
case ArrayList:
result = new ListObjectValue();
break;
case TreeMap:
result = new TreeMapObjectValue();
break;
case HashMap:
result = new HashMapObjectValue();
break;
case LinkedHashMap:
result = new LinkedHashMapObjectValue();
break;
default:
throw WorthUtils.newThrowable(IllegalArgumentException.class,
"Unknown value of %s: %s",
Implementation.class.getName(),
implementation);
}
return result;
}
@Override
default Type type() {
return Type.OBJECT;
}
enum Implementation {
ArrayList, TreeMap, HashMap, LinkedHashMap
}
}
final class ObjectEntry<K, V> implements Map.Entry<K, V> {
@@ -55,14 +74,10 @@ final class ObjectEntry<K, V> implements Map.Entry<K, V> {
}
@EqualsAndHashCode
class MapObjectValue implements ObjectValue {
abstract class MapObjectValue implements ObjectValue {
private final Map<String, Value> value;
public MapObjectValue() {
this.value = ObjectValue.preserveKeyOrder ? new LinkedHashMap<>() : new HashMap<>();
}
public MapObjectValue(Map<String, Value> value) {
this.value = value;
}
@@ -114,6 +129,31 @@ class MapObjectValue implements ObjectValue {
}
}
@EqualsAndHashCode
class HashMapObjectValue extends MapObjectValue {
public HashMapObjectValue() {
super(new HashMap<>());
}
}
@EqualsAndHashCode
class LinkedHashMapObjectValue extends MapObjectValue {
public LinkedHashMapObjectValue() {
super(new LinkedHashMap<>());
}
}
@EqualsAndHashCode
class TreeMapObjectValue extends MapObjectValue {
public TreeMapObjectValue() {
super(new TreeMap<>());
}
}
@NoArgsConstructor
@EqualsAndHashCode
class ListObjectValue implements ObjectValue {
@@ -126,7 +166,7 @@ class ListObjectValue implements ObjectValue {
@Override
public Map<String, Value> asObject() {
Map<String, Value> result = preserveKeyOrder ? new LinkedHashMap<>() : new HashMap<>();
Map<String, Value> result = new LinkedHashMap<>();
for (Map.Entry<String, Value> entry : value) {
result.put(entry.getKey(), entry.getValue());
}

View File

@@ -1,10 +1,10 @@
package net.woggioni.worth.antlr;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.xface.Value;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
import net.woggioni.worth.serialization.ValueParser;
import net.woggioni.worth.xface.Value;
public class JSONListenerImpl extends ValueParser implements JSONListener {

View File

@@ -1,13 +1,13 @@
package net.woggioni.worth.antlr;
import lombok.SneakyThrows;
import net.woggioni.worth.serialization.json.JSONDumper;
import net.woggioni.worth.xface.Value;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.Test;
import net.woggioni.worth.serialization.json.JSONDumper;
import java.io.InputStreamReader;

View File

@@ -1,13 +1,13 @@
package net.woggioni.worth.serialization.binary;
import lombok.SneakyThrows;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.serialization.json.JSONParser;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import java.io.*;
import java.lang.reflect.Method;
@@ -26,7 +26,7 @@ public class JBONTest {
@Test
@SneakyThrows
public void consistencyTest() {
System.setProperty(ObjectValue.class.getName() + ".preserveKeyOrder", "true");
System.setProperty(ObjectValue.class.getName() + ".implementation", "TreeMap");
for (String testFile : testFiles) {
Value parsedValue;
try(InputStream is = getTestSource(testFile)) {
@@ -59,7 +59,7 @@ public class JBONTest {
for (String testFile : testFiles) {
Value originalValue = new JSONParser().parse(getTestSource(testFile));
Path outputFile = Files.createTempFile(Paths.get("/tmp"),"worh", null);
Path outputFile = Files.createTempFile(Paths.get("/tmp"),"worth", null);
try (OutputStream os = new FileOutputStream(outputFile.toFile())) {
JBONDumper jbonDumper = new JBONDumper();
jbonDumper.dump(originalValue, os);

View File

@@ -4,8 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import lombok.SneakyThrows;
import org.junit.Assert;
import org.junit.Test;
import net.woggioni.worth.buffer.LookAheadTextInputStream;
import net.woggioni.worth.exception.NotImplementedException;
import net.woggioni.worth.utils.WorthUtils;
@@ -13,6 +11,8 @@ import net.woggioni.worth.value.ArrayValue;
import net.woggioni.worth.value.ObjectValue;
import net.woggioni.worth.xface.Parser;
import net.woggioni.worth.xface.Value;
import org.junit.Assert;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -186,7 +186,7 @@ public class JSONTest {
@Test
@SneakyThrows
public void consistencyTest() {
System.setProperty(ObjectValue.class.getName() + ".preserveKeyOrder", "true");
System.setProperty(ObjectValue.class.getName() + ".implementation", "ArrayList");
for (String testFile : testFiles) {
Parser parser = new JSONParser();
Value parsedValue = parser.parse(getTestSource(testFile));

View File

@@ -3,18 +3,20 @@ package net.woggioni.worth.serialization.json;
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.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.junit.Ignore;
import org.junit.Test;
import net.woggioni.worth.antlr.JSONLexer;
import net.woggioni.worth.xface.Value;
import org.tukaani.xz.XZInputStream;
import java.io.*;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
class Chronometer {
@@ -52,7 +54,11 @@ public class PerformanceTest {
@SneakyThrows
private static InputStream extractTestData() {
return new XZInputStream(PerformanceTest.class.getResourceAsStream("/citylots.json.xz"));
return new XZInputStream(new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/citylots.json.xz")));
}
private static InputStream smallTestData() {
return new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/wordpress.json"));
}
@Test
@@ -72,32 +78,37 @@ public class PerformanceTest {
Chronometer chr = new Chronometer();
{
ObjectMapper om = new ObjectMapper();
chr.reset();
for (int i = 0; i < loops; i++) {
JsonNode jsonNode = om.readTree(getClass().getResourceAsStream("/wordpress.json"));
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));
}
{
chr.reset();
for (int i = 0; i < loops; i++) {
Value value = new JSONParser().parse(getClass().getResourceAsStream("/wordpress.json"));
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));
}
{
chr.reset();
for (int i = 0; i < loops; i++) {
CharStream inputStream = CharStreams.fromReader(
new InputStreamReader(getClass().getResourceAsStream("/wordpress.json")));
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());
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));