From 08cd8491024183a90043acc4f40e01dc0369910c Mon Sep 17 00:00:00 2001 From: Sebastian Toepfer <61313468+sebastian-toepfer@users.noreply.github.com> Date: Wed, 20 Dec 2023 22:13:48 +0100 Subject: [PATCH] remove calls to static method from Json --- benchmark/pom.xml | 120 ++++++++++++++++++ .../benchmark/JsonObjectMediaBenchmarks.java | 56 ++++++++ .../ddd/media/json/JsonObjectMedia.java | 36 ++++-- .../JsonArrayStreamMediaPrintableAdapter.java | 20 ++- .../json/stream/JsonObjectStreamMedia.java | 12 +- .../util/CollectionToJsonValueMapper.java | 8 +- .../json/util/ObjectToJsonValueMapper.java | 22 ++-- .../stream/JsonObjectStreamMediaTest.java | 3 +- .../json/stream/TerminableDecoratorTest.java | 3 +- pom.xml | 32 ++++- 10 files changed, 277 insertions(+), 35 deletions(-) create mode 100644 benchmark/pom.xml create mode 100644 benchmark/src/main/java/io/github/sebastiantoepfer/ddd/benchmark/JsonObjectMediaBenchmarks.java diff --git a/benchmark/pom.xml b/benchmark/pom.xml new file mode 100644 index 0000000..45b321a --- /dev/null +++ b/benchmark/pom.xml @@ -0,0 +1,120 @@ + + + + 4.0.0 + + + io.github.sebastian-toepfer.ddd + domain-driven-desgin + 0.6.0-SNAPSHOT + + + media-benchmark + Domain Driven Desgin :: benchmark + + + true + + + + + org.openjdk.jmh + jmh-core + + + + ${project.groupId} + media-json-api + ${project.version} + + + jakarta.json + jakarta.json-api + + + org.eclipse.parsson + parsson + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + default-testCompile + + true + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + true + + + + + org.pitest + pitest-maven + + true + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + \ No newline at end of file diff --git a/benchmark/src/main/java/io/github/sebastiantoepfer/ddd/benchmark/JsonObjectMediaBenchmarks.java b/benchmark/src/main/java/io/github/sebastiantoepfer/ddd/benchmark/JsonObjectMediaBenchmarks.java new file mode 100644 index 0000000..a129b96 --- /dev/null +++ b/benchmark/src/main/java/io/github/sebastiantoepfer/ddd/benchmark/JsonObjectMediaBenchmarks.java @@ -0,0 +1,56 @@ +/* + * The MIT License + * + * Copyright 2023 sebastian. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.github.sebastiantoepfer.ddd.benchmark; + +import io.github.sebastiantoepfer.ddd.media.json.JsonObjectMedia; +import jakarta.json.spi.JsonProvider; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; + +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 7, timeUnit = TimeUnit.SECONDS) +@BenchmarkMode(Mode.AverageTime) +public class JsonObjectMediaBenchmarks { + + private static final JsonProvider JSONP = JsonProvider.provider(); + + @Benchmark + public void printAsJsonObject() { + var unused = IntStream + .range(1, 100) + .boxed() + .reduce( + new JsonObjectMedia(JSONP), + (JsonObjectMedia media, Integer value) -> media.withValue(String.valueOf(value), value), + (left, right) -> null + ); + } +} diff --git a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/JsonObjectMedia.java b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/JsonObjectMedia.java index 67f2095..6db5367 100644 --- a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/JsonObjectMedia.java +++ b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/JsonObjectMedia.java @@ -3,13 +3,13 @@ import io.github.sebastiantoepfer.ddd.common.Printable; import io.github.sebastiantoepfer.ddd.media.core.BaseMedia; import io.github.sebastiantoepfer.ddd.media.json.util.CollectionToJsonValueMapper; -import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonNumber; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import jakarta.json.JsonString; import jakarta.json.JsonValue; +import jakarta.json.spi.JsonProvider; import java.math.BigDecimal; import java.math.BigInteger; import java.util.AbstractMap; @@ -18,49 +18,56 @@ public class JsonObjectMedia extends AbstractMap implements BaseMedia, JsonObject { + private static final JsonProvider JSONP = JsonProvider.provider(); + private final JsonProvider jsonProvider; private final JsonObject json; public JsonObjectMedia() { - this(Json.createObjectBuilder()); + this(JSONP); } - private JsonObjectMedia(final JsonObjectBuilder builder) { + public JsonObjectMedia(final JsonProvider jsonProvider) { + this(jsonProvider, jsonProvider.createObjectBuilder()); + } + + private JsonObjectMedia(final JsonProvider jsonProvider, final JsonObjectBuilder builder) { + this.jsonProvider = jsonProvider; this.json = builder.build(); } @Override public JsonObjectMedia withValue(final String name, final String value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final int value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final long value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final double value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final BigDecimal value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final BigInteger value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override public JsonObjectMedia withValue(final String name, final boolean value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override @@ -71,13 +78,14 @@ public JsonObjectMedia withValue(final String name, final Printable value) { @Override public JsonObjectMedia withValue(final String name, final Collection values) { return new JsonObjectMedia( - Json.createObjectBuilder(json).add(name, new CollectionToJsonValueMapper(values).asJsonValue()) + jsonProvider, + asJsonBuilder().add(name, new CollectionToJsonValueMapper(jsonProvider, values).asJsonValue()) ); } @Override public JsonObjectMedia withValue(final String name, final JsonObjectMedia value) { - return new JsonObjectMedia(Json.createObjectBuilder(json).add(name, value)); + return new JsonObjectMedia(jsonProvider, asJsonBuilder().add(name, value)); } @Override @@ -85,6 +93,10 @@ public String toString() { return json.toString(); } + private JsonObjectBuilder asJsonBuilder() { + return jsonProvider.createObjectBuilder(json); + } + @Override public JsonArray getJsonArray(final String string) { return json.getJsonArray(string); diff --git a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonArrayStreamMediaPrintableAdapter.java b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonArrayStreamMediaPrintableAdapter.java index 2d8db53..0230e9a 100644 --- a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonArrayStreamMediaPrintableAdapter.java +++ b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonArrayStreamMediaPrintableAdapter.java @@ -24,7 +24,7 @@ package io.github.sebastiantoepfer.ddd.media.json.stream; import io.github.sebastiantoepfer.ddd.common.Printable; -import jakarta.json.Json; +import jakarta.json.spi.JsonProvider; import jakarta.json.stream.JsonGenerator; import java.io.Flushable; import java.io.IOException; @@ -34,6 +34,8 @@ public final class JsonArrayStreamMediaPrintableAdapter implements Flushable, AutoCloseable { + private static final JsonProvider JSONP = JsonProvider.provider(); + private final JsonProvider jsonProvider; private final JsonGenerator generator; private final Function> mediaDecorator; @@ -45,13 +47,23 @@ public JsonArrayStreamMediaPrintableAdapter( final OutputStream os, final Function> mediaDecorator ) { - this(Json.createGenerator(os), mediaDecorator); + this(JSONP, os, mediaDecorator); + } + + public JsonArrayStreamMediaPrintableAdapter( + final JsonProvider provider, + final OutputStream os, + final Function> mediaDecorator + ) { + this(provider, provider.createGenerator(os), mediaDecorator); } private JsonArrayStreamMediaPrintableAdapter( + final JsonProvider jsonProvider, final JsonGenerator generator, final Function> mediaDecorator ) { + this.jsonProvider = Objects.requireNonNull(jsonProvider); this.generator = Objects.requireNonNull(generator).writeStartArray(); this.mediaDecorator = Objects.requireNonNull(mediaDecorator); } @@ -73,7 +85,9 @@ public JsonArrayStreamMediaPrintableAdapter end() { } public JsonArrayStreamMediaPrintableAdapter print(final Printable printable) { - printable.printOn((TerminableMedia) mediaDecorator.apply(new JsonObjectStreamMedia(generator))).end(); + printable + .printOn((TerminableMedia) mediaDecorator.apply(new JsonObjectStreamMedia(jsonProvider, generator))) + .end(); return this; } } diff --git a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMedia.java b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMedia.java index 13144de..07a5a55 100644 --- a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMedia.java +++ b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMedia.java @@ -28,8 +28,8 @@ import io.github.sebastiantoepfer.ddd.common.Printable; import io.github.sebastiantoepfer.ddd.media.json.util.ObjectToJsonValueMapper; import io.github.sebastiantoepfer.ddd.media.json.util.ToJsonValueMapper; -import jakarta.json.Json; import jakarta.json.JsonValue; +import jakarta.json.spi.JsonProvider; import jakarta.json.stream.JsonGenerator; import java.io.Flushable; import java.io.IOException; @@ -41,13 +41,15 @@ public final class JsonObjectStreamMedia implements TerminableMedia, AutoCloseable, Flushable { + private final JsonProvider provider; private final JsonGenerator generator; - public JsonObjectStreamMedia(final OutputStream os) { - this(Json.createGenerator(os)); + public JsonObjectStreamMedia(final JsonProvider provider, final OutputStream os) { + this(provider, provider.createGenerator(os)); } - JsonObjectStreamMedia(final JsonGenerator generator) { + JsonObjectStreamMedia(final JsonProvider provider, final JsonGenerator generator) { + this.provider = Objects.requireNonNull(provider); this.generator = Objects.requireNonNull(generator).writeStartObject(); } @@ -123,7 +125,7 @@ public JsonObjectStreamMedia withValue(final String name, final Collection va generator.writeStartArray(name); values .stream() - .map(ObjectToJsonValueMapper::new) + .map(o -> new ObjectToJsonValueMapper(provider, o)) .map(ToJsonValueMapper::asJsonValue) .filter(not(value -> value.getValueType() == JsonValue.ValueType.NULL)) .forEach(generator::write); diff --git a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/CollectionToJsonValueMapper.java b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/CollectionToJsonValueMapper.java index a7f0799..ba277d4 100644 --- a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/CollectionToJsonValueMapper.java +++ b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/CollectionToJsonValueMapper.java @@ -4,14 +4,18 @@ import jakarta.json.JsonArray; import jakarta.json.JsonValue; +import jakarta.json.spi.JsonProvider; import java.util.Collection; import java.util.List; +import java.util.Objects; public class CollectionToJsonValueMapper implements ToJsonValueMapper { + private final JsonProvider jsonProvider; private final Collection values; - public CollectionToJsonValueMapper(final Collection values) { + public CollectionToJsonValueMapper(final JsonProvider jsonProvider, final Collection values) { + this.jsonProvider = Objects.requireNonNull(jsonProvider); this.values = List.copyOf(values); } @@ -19,7 +23,7 @@ public CollectionToJsonValueMapper(final Collection values) { public JsonArray asJsonValue() { return values .stream() - .map(ObjectToJsonValueMapper::new) + .map(o -> new ObjectToJsonValueMapper(jsonProvider, o)) .map(ToJsonValueMapper::asJsonValue) .filter(value -> value.getValueType() != JsonValue.ValueType.NULL) .collect(toJsonArray()); diff --git a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/ObjectToJsonValueMapper.java b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/ObjectToJsonValueMapper.java index b1a0876..25dedc1 100644 --- a/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/ObjectToJsonValueMapper.java +++ b/media-json-api/src/main/java/io/github/sebastiantoepfer/ddd/media/json/util/ObjectToJsonValueMapper.java @@ -2,17 +2,19 @@ import io.github.sebastiantoepfer.ddd.common.Printable; import io.github.sebastiantoepfer.ddd.media.json.JsonObjectMedia; -import jakarta.json.Json; import jakarta.json.JsonValue; +import jakarta.json.spi.JsonProvider; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; public class ObjectToJsonValueMapper implements ToJsonValueMapper { + private final JsonProvider jsonProvider; private final Object o; - public ObjectToJsonValueMapper(final Object o) { + public ObjectToJsonValueMapper(final JsonProvider jsonProvider, final Object o) { + this.jsonProvider = jsonProvider; this.o = o; } @@ -20,25 +22,25 @@ public ObjectToJsonValueMapper(final Object o) { public JsonValue asJsonValue() { final JsonValue result; if (o instanceof String stringValue) { - result = Json.createValue(stringValue); + result = jsonProvider.createValue(stringValue); } else if (o instanceof Integer intValue) { - result = Json.createValue(intValue); + result = jsonProvider.createValue(intValue); } else if (o instanceof Long longValue) { - result = Json.createValue(longValue); + result = jsonProvider.createValue(longValue); } else if (o instanceof Double doubleValue) { - result = Json.createValue(doubleValue); + result = jsonProvider.createValue(doubleValue); } else if (o instanceof Float floatValue) { - result = Json.createValue(floatValue.doubleValue()); + result = jsonProvider.createValue(floatValue.doubleValue()); } else if (o instanceof BigDecimal decimalValue) { - result = Json.createValue(decimalValue); + result = jsonProvider.createValue(decimalValue); } else if (o instanceof BigInteger intValue) { - result = Json.createValue(intValue); + result = jsonProvider.createValue(intValue); } else if (o instanceof Boolean boolValue) { result = Boolean.TRUE.equals(boolValue) ? JsonValue.TRUE : JsonValue.FALSE; } else if (o instanceof Printable printable) { result = printable.printOn(new JsonObjectMedia()); } else if (o instanceof Collection col) { - result = new CollectionToJsonValueMapper(col).asJsonValue(); + result = new CollectionToJsonValueMapper(jsonProvider, col).asJsonValue(); } else { result = JsonValue.NULL; } diff --git a/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMediaTest.java b/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMediaTest.java index 69e6b24..262f881 100644 --- a/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMediaTest.java +++ b/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/JsonObjectStreamMediaTest.java @@ -29,6 +29,7 @@ import io.github.sebastiantoepfer.ddd.common.Media; import io.github.sebastiantoepfer.ddd.common.Printable; import jakarta.json.Json; +import jakarta.json.spi.JsonProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.List; @@ -43,7 +44,7 @@ class JsonObjectStreamMediaTest { @BeforeEach void initMedia() { baos = new ByteArrayOutputStream(); - media = new JsonObjectStreamMedia(baos); + media = new JsonObjectStreamMedia(JsonProvider.provider(), baos); } @Test diff --git a/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/TerminableDecoratorTest.java b/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/TerminableDecoratorTest.java index 0263706..61a8ea5 100644 --- a/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/TerminableDecoratorTest.java +++ b/media-json-api/src/test/java/io/github/sebastiantoepfer/ddd/media/json/stream/TerminableDecoratorTest.java @@ -31,6 +31,7 @@ import io.github.sebastiantoepfer.ddd.media.core.decorator.TranslateNameDecorator; import io.github.sebastiantoepfer.ddd.media.core.decorator.Translator; import jakarta.json.Json; +import jakarta.json.spi.JsonProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; @@ -52,7 +53,7 @@ void initMedia() { media = new TerminableDecorator( new TranslateNameDecorator<>( - new JsonObjectStreamMedia(baos), + new JsonObjectStreamMedia(JsonProvider.provider(), baos), new Translator() { @Override public Optional translate(final String translate) { diff --git a/pom.xml b/pom.xml index d1c9b74..88ba03f 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,7 @@ 2.4.0 1.4.14 5.2.5 + 1.37 @@ -68,7 +69,7 @@ media-logging media-json-api media-logging-slf4j - media-poi-spreadsheet + media-poi-spreadsheet @@ -95,6 +96,12 @@ ${poi.version} + + org.openjdk.jmh + jmh-core + ${jmh.version} + + org.junit junit-bom @@ -471,6 +478,17 @@ + + full + + true + + + + benchmark + + + ci @@ -512,6 +530,10 @@ bump-patch + + benchmark + + @@ -542,6 +564,10 @@ bump-minor + + benchmark + + @@ -572,6 +598,10 @@ bump-major + + benchmark + +