Mercurial > stress-tester
changeset 506:6f28783661b5
JSONPath benchmark
author | Devel 1 |
---|---|
date | Thu, 17 Aug 2017 14:33:32 +0200 |
parents | c10b0d35b676 |
children | f91dee0f0bbc |
files | stress-tester-benchmark/pom.xml stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/CsrfBenchmark.java stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/JsonValueExtractorBenchmark.java |
diffstat | 3 files changed, 299 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/stress-tester-benchmark/pom.xml Thu Aug 17 11:21:35 2017 +0200 +++ b/stress-tester-benchmark/pom.xml Thu Aug 17 14:33:32 2017 +0200 @@ -152,6 +152,23 @@ <artifactId>jsoup</artifactId> <version>1.9.2</version> </dependency> + + <dependency> + <groupId>com.jayway.jsonpath</groupId> + <artifactId>json-path</artifactId> + <version>2.4.0</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.6.2</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.0</version> + </dependency> + </dependencies> <build>
--- a/stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/CsrfBenchmark.java Thu Aug 17 11:21:35 2017 +0200 +++ b/stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/CsrfBenchmark.java Thu Aug 17 14:33:32 2017 +0200 @@ -118,7 +118,7 @@ public static void main(String[] args) throws Throwable { Options opt = new OptionsBuilder().include(CsrfBenchmark.class.getSimpleName() + ".*").build(); -// new Runner(opt).run(); + new Runner(opt).run(); CsrfBenchmark cb = new CsrfBenchmark(); cb.setup(); AllocationUtils au = new AllocationUtils();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/JsonValueExtractorBenchmark.java Thu Aug 17 14:33:32 2017 +0200 @@ -0,0 +1,281 @@ +package com.passus.st.client.http.filter; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.JsonPath; +import static com.jayway.jsonpath.Option.DEFAULT_PATH_LEAF_TO_NULL; +import com.jayway.jsonpath.spi.json.GsonJsonProvider; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; +import com.passus.utils.AllocationUtils; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * + * @author mikolaj.podbielski + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Fork(value = 1) +@Measurement(iterations = 6) +@Warmup(iterations = 6) +public class JsonValueExtractorBenchmark { + + private final Configuration cfgSimple = cfgBuilder().build(); + private final Configuration cfgGson = cfgBuilder().jsonProvider(new GsonJsonProvider()).build(); + private final Configuration cfgJackson = cfgBuilder().jsonProvider(new JacksonJsonProvider()).build(); + + private static Configuration.ConfigurationBuilder cfgBuilder() { + return Configuration.builder().options(DEFAULT_PATH_LEAF_TO_NULL); + } + + public static void main(String[] args) throws Throwable { + JsonValueExtractorBenchmark bench = new JsonValueExtractorBenchmark(); //.extractLongGsonEx(); + Options opt = new OptionsBuilder().include(JsonValueExtractorBenchmark.class.getSimpleName() + ".*").build(); + new Runner(opt).run(); + AllocationUtils au = new AllocationUtils(); + au.checkAllocation(bench); + au.checkAllocation(bench); + + /* + speed: simple = jackson 2.9.0 > jackson 2.4.5 > gson + compiled > raw + alloc: jackson > simple > gson + compiled > raw + + simple 0% faster than jackson 2.9.0 + simple 6% faster than jackson 2.4.5 + jackson 35% less allocation than simple + */ + } + + private final String jsonShort = "{\n" + + " \"node1\": \"value1\",\n" + + " \"node3\": {\"node4\": \"value4\"},\n" + + " \"emptyObject\": {}\n" + + "}"; + private final String jsonLong = "{\n" + + " \"node1\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node2\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node3\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node4\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node5\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node6\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node7\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node8\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"node9\": {\n" + + " \"node0\": {\n" + + " \"node_a\": \"A\",\n" + + " \"node_b\": \"B\",\n" + + " \"node_c\": \"C\"\n" + + " },\n" + + " \"node4\": \"value4\"\n" + + " },\n" + + " \"emptyString\": \"\",\n" + + " \"emptyObject\": {},\n" + + " \"emptyArray\": []\n" + + "}"; + + private final String pathExists = "$.node3.node4"; + private final String pathDoesNotExist = "$.node3.node5"; + + private final JsonPath compiledExists = JsonPath.compile(pathExists); + private final JsonPath compiledDoesNotExist = JsonPath.compile(pathDoesNotExist); + + public Object extract(Configuration cfg, String json, String path) { + return JsonPath.using(cfg).parse(json).read(path); + } + + public Object extract(Configuration cfg, String json, JsonPath path) { + return JsonPath.using(cfg).parse(json).read(path); + } + + ////////////////////////////// + @Benchmark + public Object extractLongSimpleEx() { + return extract(cfgSimple, jsonLong, pathExists); + } + + @Benchmark + public Object extractLongSimpleNEx() { + return extract(cfgSimple, jsonLong, pathDoesNotExist); + } + + @Benchmark + public Object extractLongSimpleCEx() { + return extract(cfgSimple, jsonLong, compiledExists); + } + + @Benchmark + public Object extractLongSimpleCNEx() { + return extract(cfgSimple, jsonLong, compiledDoesNotExist); + } + + @Benchmark + public Object extractLongGsonEx() { + return extract(cfgGson, jsonLong, pathExists); + } + + @Benchmark + public Object extractLongGsonNEx() { + return extract(cfgGson, jsonLong, pathDoesNotExist); + } + + @Benchmark + public Object extractLongGsonCEx() { + return extract(cfgGson, jsonLong, compiledExists); + } + + @Benchmark + public Object extractLongGsonCNEx() { + return extract(cfgGson, jsonLong, compiledDoesNotExist); + } + + @Benchmark + public Object extractLongJacksonEx() { + return extract(cfgJackson, jsonLong, pathExists); + } + + @Benchmark + public Object extractLongJacksonNEx() { + return extract(cfgJackson, jsonLong, pathDoesNotExist); + } + + @Benchmark + public Object extractLongJacksonCEx() { + return extract(cfgJackson, jsonLong, compiledExists); + } + + @Benchmark + public Object extractLongJacksonCNEx() { + return extract(cfgJackson, jsonLong, compiledDoesNotExist); + } + + ////////////////////////////// + @Benchmark + public Object extractShortSimpleEx() { + return extract(cfgSimple, jsonShort, pathExists); + } + + @Benchmark + public Object extractShortSimpleNEx() { + return extract(cfgSimple, jsonShort, pathDoesNotExist); + } + + @Benchmark + public Object extractShortSimpleCEx() { + return extract(cfgSimple, jsonShort, compiledExists); + } + + @Benchmark + public Object extractShortSimpleCNEx() { + return extract(cfgSimple, jsonShort, compiledDoesNotExist); + } + + @Benchmark + public Object extractShortGsonEx() { + return extract(cfgGson, jsonShort, pathExists); + } + + @Benchmark + public Object extractShortGsonNEx() { + return extract(cfgGson, jsonShort, pathDoesNotExist); + } + + @Benchmark + public Object extractShortGsonCEx() { + return extract(cfgGson, jsonShort, compiledExists); + } + + @Benchmark + public Object extractShortGsonCNEx() { + return extract(cfgGson, jsonShort, compiledDoesNotExist); + } + + @Benchmark + public Object extractShortJacksonEx() { + return extract(cfgJackson, jsonShort, pathExists); + } + + @Benchmark + public Object extractShortJacksonNEx() { + return extract(cfgJackson, jsonShort, pathDoesNotExist); + } + + @Benchmark + public Object extractShortJacksonCEx() { + return extract(cfgJackson, jsonShort, compiledExists); + } + + @Benchmark + public Object extractShortJacksonCNEx() { + return extract(cfgJackson, jsonShort, compiledDoesNotExist); + } +}