added system property to switch object value implementation
This commit is contained in:
@@ -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() {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
|
@@ -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));
|
||||
|
Reference in New Issue
Block a user