18
18
import org .openjdk .jmh .annotations .Scope ;
19
19
import org .openjdk .jmh .annotations .Setup ;
20
20
import org .openjdk .jmh .annotations .State ;
21
+ import org .openjdk .jmh .runner .Runner ;
22
+ import org .openjdk .jmh .runner .options .OptionsBuilder ;
23
+ import org .openjdk .jmh .runner .options .TimeValue ;
21
24
22
25
import java .io .ByteArrayInputStream ;
23
26
import java .io .IOException ;
24
27
import java .io .InputStreamReader ;
28
+ import java .io .StringReader ;
29
+ import java .nio .charset .Charset ;
25
30
import java .nio .charset .StandardCharsets ;
26
31
import java .util .Map ;
27
32
import java .util .concurrent .ThreadLocalRandom ;
@@ -51,7 +56,8 @@ <F extends JsonFactory, B extends TSFBuilder<F, B>> B apply(B factory) {
51
56
<F extends JsonFactory , B extends TSFBuilder <F , B >> B apply (B factory ) {
52
57
return factory .disable (JsonFactory .Feature .CANONICALIZE_FIELD_NAMES );
53
58
}
54
- };
59
+ },
60
+ ;
55
61
56
62
abstract <F extends JsonFactory , B extends TSFBuilder <F , B >> B apply (B factory );
57
63
}
@@ -62,38 +68,79 @@ <F extends JsonFactory, B extends TSFBuilder<F, B>> B apply(B factory) {
62
68
public enum InputType {
63
69
INPUT_STREAM () {
64
70
@ Override
65
- JsonParser create (JsonFactory factory , Supplier <String > jsonSupplier ) throws IOException {
66
- return factory .createParser (new ByteArrayInputStream (jsonSupplier .get (). getBytes ( StandardCharsets . UTF_8 )));
71
+ JsonParser create (JsonFactory factory , Supplier <byte []> bytesSupplier ) throws IOException {
72
+ return factory .createParser (new ByteArrayInputStream (bytesSupplier .get ()));
67
73
}
68
74
},
69
75
READER () {
70
76
@ Override
71
- JsonParser create (JsonFactory factory , Supplier <String > jsonSupplier ) throws IOException {
72
- // Instead of using 'new StringReader(jsonSupplier .get())', we construct an InputStreamReader
77
+ JsonParser create (JsonFactory factory , Supplier <byte []> bytesSupplier ) throws IOException {
78
+ // Instead of using 'new StringReader(bytesSupplier .get())', we construct an InputStreamReader
73
79
// to more closely match overhead of INPUT_STREAM for comparison.
74
80
return factory .createParser (new InputStreamReader (
75
- new ByteArrayInputStream (jsonSupplier .get (). getBytes ( StandardCharsets . UTF_8 )),
81
+ new ByteArrayInputStream (bytesSupplier .get ()),
76
82
StandardCharsets .UTF_8 ));
77
83
}
78
- };
84
+ },
85
+ STRING_READER () {
86
+ @ Override
87
+ JsonParser create (JsonFactory factory , Supplier <byte []> jsonSupplier ) throws IOException {
88
+ StringReader reader = new StringReader (new String (jsonSupplier .get (), Charset .forName ("UTF-8" )));
89
+ return factory .createParser (reader );
90
+ }
91
+ },
92
+ ;
79
93
80
- abstract JsonParser create (JsonFactory factory , Supplier <String > jsonSupplier ) throws IOException ;
94
+ abstract JsonParser create (JsonFactory factory , Supplier <byte [] > jsonSupplier ) throws IOException ;
81
95
}
82
96
83
97
public enum InputShape {
98
+ KEY_MAP (
99
+ new TypeReference <Map <String , Boolean >>() {
100
+ },
101
+ () -> "{\" key\" :true}" ),
84
102
RANDOM_KEY_MAP (
85
- new TypeReference <Map <String , Boolean >>() {},
103
+ new TypeReference <Map <String , Boolean >>() {
104
+ },
86
105
() -> "{\" " + ThreadLocalRandom .current ().nextInt () + "\" :true}" ),
87
106
BEAN_WITH_RANDOM_KEY_MAP (
88
- new TypeReference <SimpleClass >() {},
107
+ new TypeReference <SimpleClass >() {
108
+ },
89
109
() -> "{\" fieldWithMap\" :{\" " + ThreadLocalRandom .current ().nextInt ()
90
- + "\" :true},\" stringOne\" :\" a\" ,\" stringTwo\" :\" a\" ,\" stringThree\" :\" a\" }" );
110
+ + "\" :true},\" stringOne\" :\" a\" ,\" stringTwo\" :\" a\" ,\" stringThree\" :\" a\" }" ),
111
+ BEAN_WITH_LARGE_KEY_MAP (
112
+ new TypeReference <SimpleClass >() {
113
+ },
114
+ new Supplier <String >() {
115
+ private final String json = generateSimpleInstanceJson (10_000 );
116
+
117
+ @ Override
118
+ public String get () {
119
+ return json ;
120
+ }
121
+ }
122
+ ),
123
+ ;
124
+
125
+ private static String generateSimpleInstanceJson (int n ) {
126
+ StringBuilder builder = new StringBuilder ();
127
+ builder .append ("{\" fieldWithMap\" :{" );
128
+ for (int i = 0 ; i < n ; i ++) {
129
+ builder .append ("\" " ).append (i ).append ("\" :" ).append (i % 2 == 0 );
130
+ if (i < n -1 ) {
131
+ builder .append (',' );
132
+ }
133
+ }
134
+ builder .append ("},\" stringOne\" :\" a\" ,\" stringTwo\" :\" a\" ,\" stringThree\" :\" a\" }" );
135
+ return builder .toString ();
136
+ }
91
137
92
138
private final TypeReference <?> typereference ;
93
- private final Supplier <String > jsonSupplier ;
139
+ private final Supplier <byte []> bytesSupplier ;
140
+
94
141
InputShape (TypeReference <?> typereference , Supplier <String > jsonSupplier ) {
95
142
this .typereference = typereference ;
96
- this .jsonSupplier = jsonSupplier ;
143
+ this .bytesSupplier = () -> jsonSupplier . get (). getBytes ( StandardCharsets . UTF_8 ) ;
97
144
}
98
145
}
99
146
@@ -121,7 +168,7 @@ public void setup() {
121
168
122
169
@ Benchmark
123
170
public Object parse () throws IOException {
124
- try (JsonParser parser = type .create (factory , shape .jsonSupplier )) {
171
+ try (JsonParser parser = type .create (factory , shape .bytesSupplier )) {
125
172
return reader .readValue (parser );
126
173
}
127
174
}
@@ -140,4 +187,16 @@ public static final class SimpleClass {
140
187
@ JsonProperty ("stringThree" )
141
188
public String stringThree ;
142
189
}
190
+
191
+ public static void main (String [] _args ) throws Exception {
192
+ new Runner (new OptionsBuilder ()
193
+ .include (JsonArbitraryFieldNameBenchmark .class .getName ())
194
+ .warmupIterations (2 )
195
+ .warmupTime (TimeValue .seconds (5 ))
196
+ .measurementIterations (4 )
197
+ .measurementTime (TimeValue .seconds (5 ))
198
+ .mode (Mode .AverageTime )
199
+ .forks (1 )
200
+ .build ()).run ();
201
+ }
143
202
}
0 commit comments