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);
+    }
+}