Skip to content

Commit 66675e4

Browse files
committed
optimize reflection
1 parent 3eb89ab commit 66675e4

13 files changed

Lines changed: 376 additions & 105 deletions

File tree

demo/src/main/java/com/jsoniter/demo/ConstructorBinding.java

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package com.jsoniter.demo;
22

33
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnore;
45
import com.fasterxml.jackson.annotation.JsonProperty;
56
import com.fasterxml.jackson.core.type.TypeReference;
67
import com.fasterxml.jackson.databind.ObjectMapper;
78
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
89
import com.jsoniter.JsonIterator;
9-
import com.jsoniter.annotation.JsoniterAnnotationSupport;
10+
import com.jsoniter.ReflectionDecoder;
11+
import com.jsoniter.annotation.JacksonAnnotationSupport;
12+
import com.jsoniter.spi.ExtensionManager;
1013
import com.jsoniter.spi.TypeLiteral;
1114
import org.junit.Test;
1215
import org.openjdk.jmh.Main;
1316
import org.openjdk.jmh.annotations.*;
17+
import org.openjdk.jmh.infra.BenchmarkParams;
1418
import org.openjdk.jmh.infra.Blackhole;
1519

1620
import java.io.IOException;
@@ -25,14 +29,15 @@ public class ConstructorBinding {
2529
private String inputStr;
2630

2731
public static class TestObject {
32+
@JsonIgnore
2833
private int field1;
34+
@JsonIgnore
2935
private int field2;
3036

3137
@JsonCreator
32-
@com.jsoniter.annotation.JsonCreator
3338
public TestObject(
34-
@JsonProperty("field1") @com.jsoniter.annotation.JsonProperty("field1") int field1,
35-
@JsonProperty("field2") @com.jsoniter.annotation.JsonProperty("field2") int field2) {
39+
@JsonProperty("field1") int field1,
40+
@JsonProperty("field2") int field2) {
3641
this.field1 = field1;
3742
this.field2 = field2;
3843
}
@@ -50,36 +55,35 @@ public String toString() {
5055
private JsonIterator iter;
5156

5257
@Setup(Level.Trial)
53-
public void benchSetup() {
58+
public void benchSetup(BenchmarkParams params) {
5459
inputStr = "{'field1':100,'field2':101}";
5560
input = inputStr.replace('\'', '"').getBytes();
5661
iter = JsonIterator.parse(input);
5762
typeLiteral = new TypeLiteral<TestObject>() {
5863
};
5964
typeRef = new TypeReference<TestObject>() {
6065
};
61-
JsoniterAnnotationSupport.enable();
66+
JacksonAnnotationSupport.enable();
6267
jackson = new ObjectMapper();
6368
jackson.registerModule(new AfterburnerModule());
69+
if (params != null) {
70+
if (params.getBenchmark().contains("withJsoniterStrictMode")) {
71+
JsonIterator.enableStrictMode();
72+
}
73+
if (params.getBenchmark().contains("withJsoniterReflection")) {
74+
ExtensionManager.registerTypeDecoder(TestObject.class, new ReflectionDecoder(TestObject.class));
75+
}
76+
}
6477
}
6578

6679
@Test
6780
public void test() throws IOException {
68-
benchSetup();
81+
benchSetup(null);
82+
ExtensionManager.registerTypeDecoder(TestObject.class, new ReflectionDecoder(TestObject.class));
6983
System.out.println(withJsoniter());
7084
System.out.println(withJackson());
7185
}
7286

73-
@Benchmark
74-
public void withJsoniter(Blackhole bh) throws IOException {
75-
bh.consume(withJsoniter());
76-
}
77-
78-
@Benchmark
79-
public void withJackson(Blackhole bh) throws IOException {
80-
bh.consume(withJackson());
81-
}
82-
8387
public static void main(String[] args) throws Exception {
8488
Main.main(new String[]{
8589
"ConstructorBinding",
@@ -89,6 +93,26 @@ public static void main(String[] args) throws Exception {
8993
});
9094
}
9195

96+
// @Benchmark
97+
public void withJsoniterHashMode(Blackhole bh) throws IOException {
98+
bh.consume(withJsoniter());
99+
}
100+
101+
// @Benchmark
102+
public void withJsoniterStrictMode(Blackhole bh) throws IOException {
103+
bh.consume(withJsoniter());
104+
}
105+
106+
@Benchmark
107+
public void withJsoniterReflection(Blackhole bh) throws IOException {
108+
bh.consume(withJsoniter());
109+
}
110+
111+
@Benchmark
112+
public void withJackson(Blackhole bh) throws IOException {
113+
bh.consume(withJackson());
114+
}
115+
92116
private TestObject withJsoniter() throws IOException {
93117
iter.reset();
94118
return iter.read(typeLiteral);

demo/src/main/java/com/jsoniter/demo/SimpleObjectBinding.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public void benchSetup(BenchmarkParams params) {
7676
@Test
7777
public void test() throws IOException {
7878
benchSetup(null);
79+
ExtensionManager.registerTypeDecoder(TestObject.class, new ReflectionDecoder(TestObject.class));
7980
System.out.println(withIterator());
8081
System.out.println(withIteratorIfElse());
8182
System.out.println(withIteratorIntern());
@@ -120,7 +121,7 @@ public void withBindApiStrictMode(Blackhole bh) throws IOException {
120121
bh.consume(withBindApi());
121122
}
122123

123-
// @Benchmark
124+
@Benchmark
124125
public void withReflection(Blackhole bh) throws IOException {
125126
bh.consume(withBindApi());
126127
}
@@ -130,12 +131,12 @@ public void withExistingObject(Blackhole bh) throws IOException {
130131
bh.consume(withExistingObject());
131132
}
132133

133-
@Benchmark
134+
// @Benchmark
134135
public void withJacksonAfterburner(Blackhole bh) throws IOException {
135136
bh.consume(withJackson());
136137
}
137138

138-
@Benchmark
139+
// @Benchmark
139140
public void withJacksonNoAfterburner(Blackhole bh) throws IOException {
140141
bh.consume(withJackson());
141142
}

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
<artifactId>javassist</artifactId>
4949
<version>3.21.0-GA</version>
5050
</dependency>
51+
<dependency>
52+
<groupId>com.fasterxml.jackson.core</groupId>
53+
<artifactId>jackson-annotations</artifactId>
54+
<version>LATEST</version>
55+
<scope>provided</scope>
56+
</dependency>
5157
</dependencies>
5258

5359
<build>

src/main/java/com/jsoniter/CodegenAccess.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.jsoniter.spi.Decoder;
44
import com.jsoniter.spi.ExtensionManager;
5+
import com.jsoniter.spi.TypeLiteral;
56

67
import java.io.IOException;
78
import java.util.Collection;
@@ -32,6 +33,45 @@ public static byte nextToken(JsonIterator iter) throws IOException {
3233
return iter.nextToken();
3334
}
3435

36+
public static final <T> T read(JsonIterator iter, TypeLiteral<T> typeLiteral) throws IOException {
37+
TypeLiteral.NativeType nativeType = typeLiteral.getNativeType();
38+
if (nativeType != null) {
39+
switch (nativeType) {
40+
case FLOAT:
41+
return (T) Float.valueOf(iter.readFloat());
42+
case DOUBLE:
43+
return (T) Double.valueOf(iter.readDouble());
44+
case BOOLEAN:
45+
return (T) Boolean.valueOf(iter.readBoolean());
46+
case BYTE:
47+
return (T) Byte.valueOf((byte) iter.readShort());
48+
case SHORT:
49+
return (T) Short.valueOf(iter.readShort());
50+
case INT:
51+
return (T) Integer.valueOf(iter.readInt());
52+
case CHAR:
53+
return (T) Character.valueOf((char) iter.readInt());
54+
case LONG:
55+
return (T) Long.valueOf(iter.readLong());
56+
case BIG_DECIMAL:
57+
return (T) iter.readBigDecimal();
58+
case BIG_INTEGER:
59+
return (T) iter.readBigInteger();
60+
case STRING:
61+
return (T) iter.readString();
62+
case OBJECT:
63+
return (T) iter.readAnyObject();
64+
case ANY:
65+
return (T) iter.readAny();
66+
default:
67+
throw new JsonException("unsupported native type: " + nativeType);
68+
}
69+
} else {
70+
String cacheKey = typeLiteral.getDecoderCacheKey();
71+
return (T) Codegen.getDecoder(cacheKey, typeLiteral.getType()).decode(iter);
72+
}
73+
}
74+
3575
public static final boolean readBoolean(String cacheKey, JsonIterator iter) throws IOException {
3676
return ((Decoder.BooleanDecoder) ExtensionManager.getDecoder(cacheKey)).decodeBoolean(iter);
3777
}

src/main/java/com/jsoniter/CodegenImplNative.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.jsoniter;
22

3-
import com.jsoniter.spi.Binding;
43
import com.jsoniter.spi.Decoder;
5-
import com.jsoniter.spi.ExtensionManager;
64
import com.jsoniter.spi.TypeLiteral;
75

86
import java.lang.reflect.ParameterizedType;

src/main/java/com/jsoniter/JsonIterator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class JsonIterator implements Closeable {
1919
int head;
2020
int tail;
2121
boolean eof;
22+
23+
Map<String, Object> tempObjects = new HashMap<String, Object>();
2224
final Slice reusableSlice = new Slice(null, 0, 0);
2325
char[] reusableChars = new char[32];
2426
Object existingObject = null; // the object should be bind to next
@@ -333,7 +335,8 @@ public final <T> T read(Class<T> clazz) throws IOException {
333335
}
334336

335337
public final <T> T read(TypeLiteral<T> typeLiteral) throws IOException {
336-
return (T) Codegen.getDecoder(typeLiteral.getDecoderCacheKey(), typeLiteral.getType()).decode(this);
338+
String cacheKey = typeLiteral.getDecoderCacheKey();
339+
return (T) Codegen.getDecoder(cacheKey, typeLiteral.getType()).decode(this);
337340
}
338341

339342
public ValueType whatIsNext() throws IOException {

0 commit comments

Comments
 (0)