diff --git a/antlr/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java b/antlr/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java index 79bf70b..7ccd1ec 100644 --- a/antlr/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java +++ b/antlr/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java @@ -6,6 +6,8 @@ import lombok.SneakyThrows; import net.woggioni.worth.antlr.JSONLexer; import net.woggioni.worth.antlr.JSONListenerImpl; import net.woggioni.worth.serialization.binary.JBONDumper; +import net.woggioni.worth.serialization.binary.JBONParser; +import net.woggioni.worth.value.ObjectValue; import net.woggioni.worth.xface.Dumper; import net.woggioni.worth.xface.Parser; import net.woggioni.worth.xface.Value; @@ -31,6 +33,11 @@ public class PerformanceTest { return new XZInputStream(new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/citylots.json.xz"))); } + @SneakyThrows + private static InputStream extractBinaryTestData() { + return new XZInputStream(new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/citylots.jbon.xz"))); + } + private static InputStream smallTestData() { return new BufferedInputStream(PerformanceTest.class.getResourceAsStream("/wordpress.json")); } @@ -95,6 +102,9 @@ public class PerformanceTest { public void hugeJSONTest() { double jacksonTime, worthTime, antlrTime; Chronometer chr = new Chronometer(); + Value.Configuration cfg = Value.Configuration.builder() + .objectValueImplementation(ObjectValue.Implementation.ArrayList) + .build(); try(InputStream is = extractTestData()) { chr.reset(); ObjectMapper om = new ObjectMapper(); @@ -104,10 +114,18 @@ public class PerformanceTest { } try(InputStream is = extractTestData()) { chr.reset(); - new JSONParser().parse(is); + new JSONParser(cfg).parse(is); worthTime = chr.stop(Chronometer.TimeUnit.SECOND); System.out.printf("Worth time: %8s sec\n", String.format("%.3f", worthTime)); } + + try(InputStream is = extractBinaryTestData()) { + chr.reset(); + new JBONParser(cfg).parse(is); + worthTime = chr.stop(Chronometer.TimeUnit.SECOND); + System.out.printf("Worth time binary: %8s sec\n", String.format("%.3f", worthTime)); + } + try(InputStream is = extractTestData()) { chr.reset(); CharStream inputStream = CharStreams.fromReader(new InputStreamReader(is)); diff --git a/src/main/java/net/woggioni/worth/serialization/ValueParser.java b/src/main/java/net/woggioni/worth/serialization/ValueParser.java index fa19a33..5bad618 100644 --- a/src/main/java/net/woggioni/worth/serialization/ValueParser.java +++ b/src/main/java/net/woggioni/worth/serialization/ValueParser.java @@ -5,14 +5,18 @@ import net.woggioni.worth.exception.MaxDepthExceededException; import net.woggioni.worth.exception.NotImplementedException; import net.woggioni.worth.exception.ParseException; import net.woggioni.worth.utils.WorthUtils; -import net.woggioni.worth.value.*; +import net.woggioni.worth.value.ArrayValue; +import net.woggioni.worth.value.BooleanValue; +import net.woggioni.worth.value.FloatValue; +import net.woggioni.worth.value.IntegerValue; +import net.woggioni.worth.value.ObjectValue; +import net.woggioni.worth.value.StringValue; import net.woggioni.worth.xface.Parser; import net.woggioni.worth.xface.Value; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.lang.reflect.Array; import java.nio.charset.Charset; import java.util.ArrayDeque; import java.util.HashMap; diff --git a/src/main/java/net/woggioni/worth/utils/Leb128.java b/src/main/java/net/woggioni/worth/utils/Leb128.java index ecd5e79..793e838 100644 --- a/src/main/java/net/woggioni/worth/utils/Leb128.java +++ b/src/main/java/net/woggioni/worth/utils/Leb128.java @@ -26,10 +26,10 @@ public class Leb128 { public static int encode(OutputStream os, long input) { int bytes_written = 0; long number = input >= 0 ? (input << 1) : (-(input + 1)) << 1 | 1; - while(number > 127) { + while((number & 127L) != number) { os.write((int) (number & 127) | 128); bytes_written++; - number >>= 7; + number >>>= 7; } os.write((int) number); return ++bytes_written; @@ -67,11 +67,10 @@ public class Leb128 { if(c < 0) { throw new IllegalArgumentException("Unexpected end of file"); } - byte b = (byte) c; - res |= ((long)(b & 127)) << (i * 7); - if(b >= 0) break; + res |= ((long)(c & 127)) << (i * 7); + if((byte) c >= 0) break; } - return (res & 1) != 0 ? - (res >> 1) - 1 : (res >> 1); + return (res & 1) != 0 ? - (res >>> 1) - 1 : (res >>> 1); } } } diff --git a/src/test/java/net/woggioni/worth/serialization/binary/JBONTest.java b/src/test/java/net/woggioni/worth/serialization/binary/JBONTest.java index fa938b1..74d89b9 100644 --- a/src/test/java/net/woggioni/worth/serialization/binary/JBONTest.java +++ b/src/test/java/net/woggioni/worth/serialization/binary/JBONTest.java @@ -9,7 +9,13 @@ import net.woggioni.worth.xface.Value; import org.junit.Assert; import org.junit.Test; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; @@ -27,26 +33,26 @@ public class JBONTest { @SneakyThrows public void consistencyTest() { Value.Configuration cfg = Value.Configuration.builder() - .objectValueImplementation(ObjectValue.Implementation.TreeMap).build(); + .objectValueImplementation(ObjectValue.Implementation.TreeMap).build(); for (String testFile : testFiles) { Value parsedValue; - try(InputStream is = getTestSource(testFile)) { + try (InputStream is = getTestSource(testFile)) { Parser parser = new JSONParser(cfg); parsedValue = parser.parse(is); } byte[] dumpedJBON; - try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { JBONDumper.newInstance().dump(parsedValue, baos); dumpedJBON = baos.toByteArray(); } Value reParsedValue; - try(InputStream is = new ByteArrayInputStream(dumpedJBON)) { + try (InputStream is = new ByteArrayInputStream(dumpedJBON)) { Parser parser = new JBONParser(cfg); reParsedValue = parser.parse(is); } Assert.assertEquals(parsedValue, reParsedValue); byte[] reDumpedJBON; - try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { JBONDumper.newInstance().dump(reParsedValue, baos); reDumpedJBON = baos.toByteArray(); } @@ -60,13 +66,13 @@ public class JBONTest { for (String testFile : testFiles) { Value originalValue = new JSONParser().parse(getTestSource(testFile)); - Path outputFile = Files.createTempFile(Paths.get("/tmp"),"worth", 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); } Value binarySerializedValue; - try(InputStream is = new FileInputStream(outputFile.toFile())) { + try (InputStream is = new FileInputStream(outputFile.toFile())) { JBONParser jbonParser = new JBONParser(); binarySerializedValue = jbonParser.parse(is); } diff --git a/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java b/src/test/java/net/woggioni/worth/serialization/json/Chronometer.java similarity index 95% rename from src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java rename to src/test/java/net/woggioni/worth/serialization/json/Chronometer.java index 0a0b266..b04d56d 100644 --- a/src/test/java/net/woggioni/worth/serialization/json/PerformanceTest.java +++ b/src/test/java/net/woggioni/worth/serialization/json/Chronometer.java @@ -1,6 +1,6 @@ package net.woggioni.worth.serialization.json; -class Chronometer { +public class Chronometer { public enum TimeUnit { NANOSECOND(1e-9), MICROSECOND(1e-6), MILLISECOND(1e-3), SECOND(1); diff --git a/src/test/java/net/woggioni/worth/utils/Leb128Test.java b/src/test/java/net/woggioni/worth/utils/Leb128Test.java index 382c42f..d7dd2f3 100644 --- a/src/test/java/net/woggioni/worth/utils/Leb128Test.java +++ b/src/test/java/net/woggioni/worth/utils/Leb128Test.java @@ -7,6 +7,7 @@ import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class Leb128Test { @@ -27,7 +28,9 @@ public class Leb128Test { @Test public void testDouble() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - List numbers = Arrays.asList(0.0, 1.5, -3.0, 0.5, 2.5, 8.25, -125.0, 255.0, 10325.0, -2000.0, 1024.0 * 1024 * 1024 * 12); + List numbers = Arrays.asList( + 0.0, 1.5, -3.0, 0.5, 2.5, 8.25, -125.0, 255.0, 10325.0, -2000.0, 1024.0 * 1024 * 1024 * 12, + -122.42200352825247, 37.80848009696725); numbers.forEach(n -> Leb128.encode(baos, n)); diff --git a/src/test/resources/citylots.jbon.xz b/src/test/resources/citylots.jbon.xz new file mode 100644 index 0000000..15b1bed Binary files /dev/null and b/src/test/resources/citylots.jbon.xz differ