From f12c6c97238f1ea73a268026f30ab6718312fede Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 27 Apr 2022 19:26:02 +0200 Subject: [PATCH 1/6] init work to support fast double parser --- .../deser/std/NumberDeserializers.java | 2 +- .../databind/deser/std/StdDeserializer.java | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java index bf59a4f6c2..5a79cfa456 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java @@ -736,7 +736,7 @@ protected final Double _parseDouble(JsonParser p, DeserializationContext ctxt) t return (Double) getNullValue(ctxt); } try { - return _parseDouble(text); + return _parseDouble(text, p.isEnabled(JsonParser.Feature.USE_FAST_DOUBLE_PARSER)); } catch (IllegalArgumentException iae) { } return (Double) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid `Double` value"); diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java index 61f261d775..c18b6c78b9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java @@ -1157,10 +1157,24 @@ protected final double _parseDoublePrimitive(DeserializationContext ctxt, String /** * Helper method for encapsulating calls to low-level double value parsing; single place * just because we need a work-around that must be applied to all calls. + * Does not use the new useFastParser support. + * + * @see #_parseDouble(String, boolean) + */ + protected final static double _parseDouble(final String numStr) throws NumberFormatException + { + return _parseDouble(numStr, false); + } + + /** + * Helper method for encapsulating calls to low-level double value parsing; single place + * just because we need a work-around that must be applied to all calls. + * + * @since 2.14 */ - protected final static double _parseDouble(String numStr) throws NumberFormatException + protected final static double _parseDouble(final String numStr, final boolean useFastParser) throws NumberFormatException { - return NumberInput.parseDouble(numStr); + return NumberInput.parseDouble(numStr, useFastParser); } /** From 73cc64d4d201d0e0d7796b2a2e07624fef1d4c18 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 9 May 2022 22:39:12 +0200 Subject: [PATCH 2/6] Update ReadValuesTest.java --- .../jackson/databind/seq/ReadValuesTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java index 75582871a4..a708b3c2d3 100644 --- a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java @@ -307,6 +307,29 @@ public void testNonRootMapsWithObjectReader() throws Exception assertEquals(2, map.size()); assertFalse(iterator.hasNext()); } + + public void testObjectReaderWithFastDoubleParser() throws Exception + { + String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; + final MappingIterator> iterator = MAPPER + .reader() + .forType(new TypeReference>(){}) + .withFeatures(JsonParser.Feature.USE_FAST_DOUBLE_PARSER) + .readValues(JSON); + + Map map; + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(2, map.size()); + assertEquals(Double.valueOf(1.23456), map.get("val1")); + assertEquals(Double.valueOf(5), map.get("val2")); + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(Double.valueOf(3.14), map.get("val1")); + assertEquals(Double.valueOf(-6.5), map.get("val2")); + assertEquals(2, map.size()); + assertFalse(iterator.hasNext()); + } public void testNonRootArraysUsingParser() throws Exception { From 482b820c909da20c87cfc79e648fb301502e80a7 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 10 May 2022 08:12:58 +0200 Subject: [PATCH 3/6] Update ReadValuesTest.java --- .../jackson/databind/seq/ReadValuesTest.java | 88 ++++++++++++++----- 1 file changed, 68 insertions(+), 20 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java index a708b3c2d3..5325a2c02a 100644 --- a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java @@ -4,6 +4,7 @@ import java.util.*; import com.fasterxml.jackson.core.*; +import com.fasterxml.jackson.core.json.JsonReadFeature; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; @@ -308,29 +309,26 @@ public void testNonRootMapsWithObjectReader() throws Exception assertFalse(iterator.hasNext()); } - public void testObjectReaderWithFastDoubleParser() throws Exception + public void testObjectReaderWithJsonParserFastDoubleParser() throws Exception { - String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; - final MappingIterator> iterator = MAPPER - .reader() - .forType(new TypeReference>(){}) - .withFeatures(JsonParser.Feature.USE_FAST_DOUBLE_PARSER) - .readValues(JSON); + testObjectReaderWithFastDoubleParser(true); + } - Map map; - assertTrue(iterator.hasNext()); - map = iterator.nextValue(); - assertEquals(2, map.size()); - assertEquals(Double.valueOf(1.23456), map.get("val1")); - assertEquals(Double.valueOf(5), map.get("val2")); - assertTrue(iterator.hasNext()); - map = iterator.nextValue(); - assertEquals(Double.valueOf(3.14), map.get("val1")); - assertEquals(Double.valueOf(-6.5), map.get("val2")); - assertEquals(2, map.size()); - assertFalse(iterator.hasNext()); + public void testObjectReaderWithJsonReadFeatureFastDoubleParser() throws Exception + { + testObjectReaderWithFastDoubleParser(false); } - + + public void testObjectReaderWithJsonParserFastFloatParser() throws Exception + { + testObjectReaderWithFastFloatParser(true); + } + + public void testObjectReaderWithJsonReadFeatureFastFloatParser() throws Exception + { + testObjectReaderWithFastFloatParser(false); + } + public void testNonRootArraysUsingParser() throws Exception { final String JSON = "[[1],[3]]"; @@ -365,4 +363,54 @@ public void testEmptyIterator() throws Exception empty.close(); } + + private void testObjectReaderWithFastDoubleParser(final boolean useParserFeature) throws Exception + { + final String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; + final ObjectReader reader = MAPPER.reader().forType(new TypeReference>(){}); + if (useParserFeature) { + reader.with(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + } else { + reader.with(JsonReadFeature.USE_FAST_DOUBLE_PARSER); + } + final MappingIterator> iterator = reader.readValues(JSON); + + Map map; + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(2, map.size()); + assertEquals(Double.valueOf(1.23456), map.get("val1")); + assertEquals(Double.valueOf(5), map.get("val2")); + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(Double.valueOf(3.14), map.get("val1")); + assertEquals(Double.valueOf(-6.5), map.get("val2")); + assertEquals(2, map.size()); + assertFalse(iterator.hasNext()); + } + + private void testObjectReaderWithFastFloatParser(final boolean useParserFeature) throws Exception + { + final String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; + final ObjectReader reader = MAPPER.reader().forType(new TypeReference>(){}); + if (useParserFeature) { + reader.with(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + } else { + reader.with(JsonReadFeature.USE_FAST_DOUBLE_PARSER); + } + final MappingIterator> iterator = reader.readValues(JSON); + + Map map; + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(2, map.size()); + assertEquals(Float.valueOf(1.23456f), map.get("val1")); + assertEquals(Float.valueOf(5), map.get("val2")); + assertTrue(iterator.hasNext()); + map = iterator.nextValue(); + assertEquals(Float.valueOf(3.14f), map.get("val1")); + assertEquals(Float.valueOf(-6.5f), map.get("val2")); + assertEquals(2, map.size()); + assertFalse(iterator.hasNext()); + } } From ab0ee23d3c88aab86f8ba9d25d490453c15aa01f Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 17 May 2022 13:38:31 +0100 Subject: [PATCH 4/6] Update ReadValuesTest.java --- .../jackson/databind/seq/ReadValuesTest.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java index 5325a2c02a..8ab3eefcb3 100644 --- a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.json.JsonMapper; @SuppressWarnings("resource") public class ReadValuesTest extends BaseMapTest @@ -367,13 +368,16 @@ public void testEmptyIterator() throws Exception private void testObjectReaderWithFastDoubleParser(final boolean useParserFeature) throws Exception { final String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; - final ObjectReader reader = MAPPER.reader().forType(new TypeReference>(){}); + final ObjectMapper mapper; if (useParserFeature) { - reader.with(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + JsonFactory factory = new JsonFactory(); + factory.enable(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + mapper = JsonMapper.builder(factory).build(); } else { - reader.with(JsonReadFeature.USE_FAST_DOUBLE_PARSER); + mapper = JsonMapper.builder().enable(JsonReadFeature.USE_FAST_DOUBLE_PARSER).build(); } - final MappingIterator> iterator = reader.readValues(JSON); + + final MappingIterator> iterator = mapper.reader().forType(new TypeReference>(){}).readValues(JSON); Map map; assertTrue(iterator.hasNext()); @@ -392,13 +396,15 @@ private void testObjectReaderWithFastDoubleParser(final boolean useParserFeature private void testObjectReaderWithFastFloatParser(final boolean useParserFeature) throws Exception { final String JSON = "[{ \"val1\": 1.23456, \"val2\": 5 }, { \"val1\": 3.14, \"val2\": -6.5 }]"; - final ObjectReader reader = MAPPER.reader().forType(new TypeReference>(){}); + final ObjectMapper mapper; if (useParserFeature) { - reader.with(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + JsonFactory factory = new JsonFactory(); + factory.enable(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); + mapper = JsonMapper.builder(factory).build(); } else { - reader.with(JsonReadFeature.USE_FAST_DOUBLE_PARSER); + mapper = JsonMapper.builder().enable(JsonReadFeature.USE_FAST_DOUBLE_PARSER).build(); } - final MappingIterator> iterator = reader.readValues(JSON); + final MappingIterator> iterator = mapper.reader().forType(new TypeReference>(){}).readValues(JSON); Map map; assertTrue(iterator.hasNext()); From c2b92953df6f451187ba0ca0716b760919dd5857 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 21 Jun 2022 01:21:40 +0100 Subject: [PATCH 5/6] Update ReadValuesTest.java --- .../com/fasterxml/jackson/databind/seq/ReadValuesTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java index 8ab3eefcb3..b3ee8136b0 100644 --- a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java @@ -4,7 +4,6 @@ import java.util.*; import com.fasterxml.jackson.core.*; -import com.fasterxml.jackson.core.json.JsonReadFeature; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.BaseMapTest; @@ -374,7 +373,7 @@ private void testObjectReaderWithFastDoubleParser(final boolean useParserFeature factory.enable(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); mapper = JsonMapper.builder(factory).build(); } else { - mapper = JsonMapper.builder().enable(JsonReadFeature.USE_FAST_DOUBLE_PARSER).build(); + mapper = JsonMapper.builder().enable(StreamReadFeature.USE_FAST_DOUBLE_PARSER).build(); } final MappingIterator> iterator = mapper.reader().forType(new TypeReference>(){}).readValues(JSON); @@ -402,7 +401,7 @@ private void testObjectReaderWithFastFloatParser(final boolean useParserFeature) factory.enable(JsonParser.Feature.USE_FAST_DOUBLE_PARSER); mapper = JsonMapper.builder(factory).build(); } else { - mapper = JsonMapper.builder().enable(JsonReadFeature.USE_FAST_DOUBLE_PARSER).build(); + mapper = JsonMapper.builder().enable(StreamReadFeature.USE_FAST_DOUBLE_PARSER).build(); } final MappingIterator> iterator = mapper.reader().forType(new TypeReference>(){}).readValues(JSON); From da3259dbcd2d2f0587eb981a91db23dff2024365 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 21 Jun 2022 01:25:37 +0100 Subject: [PATCH 6/6] Update NumberDeserializers.java --- .../jackson/databind/deser/std/NumberDeserializers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java index 5a79cfa456..6fc440b8b6 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java @@ -645,7 +645,7 @@ protected final Float _parseFloat(JsonParser p, DeserializationContext ctxt) return (Float) getNullValue(ctxt); } try { - return NumberInput.parseFloat(text); + return NumberInput.parseFloat(text, p.isEnabled(JsonParser.Feature.USE_FAST_DOUBLE_PARSER)); } catch (IllegalArgumentException iae) { } return (Float) ctxt.handleWeirdStringValue(_valueClass, text, "not a valid `Float` value");