improved performance

This commit is contained in:
高铁
2016-04-02 19:32:51 +08:00
parent af61c7cd59
commit 56f00a8e29
11 changed files with 173 additions and 55 deletions
+2 -1
View File
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.JSONLexer;
@@ -679,7 +680,7 @@ public abstract class JSON implements JSONStreamAware, JSONAware {
}
try {
List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);
List<FieldInfo> getters = TypeUtils.computeGetters(clazz, clazz.getAnnotation(JSONType.class), null, false);
JSONObject json = new JSONObject(getters.size());
@@ -192,7 +192,7 @@ public class DefaultJSONParser extends AbstractJSONParser implements Closeable {
final JSONLexer lexer = this.lexer;
if (lexer.token() == JSONToken.NULL) {
lexer.next();
lexer.nextToken();
return null;
}
@@ -473,7 +473,7 @@ public class ParserConfig {
public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
boolean asmEnable = this.asmEnable;
if (asmEnable) {
Class<?> superClass = DeserializeBeanInfo.getBuilderClass(clazz);
Class<?> superClass = DeserializeBeanInfo.getBuilderClass(clazz.getAnnotation(JSONType.class));
if (superClass == null) {
superClass = clazz;
}
@@ -10,7 +10,9 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -122,8 +124,10 @@ public class ASMSerializerFactory implements Opcodes {
if (clazz.isPrimitive()) {
throw new JSONException("unsupportd class " + clazz.getName());
}
JSONType jsonType = clazz.getAnnotation(JSONType.class);
List<FieldInfo> getters = TypeUtils.computeGetters(clazz, aliasMap, false);
List<FieldInfo> getters = TypeUtils.computeGetters(clazz, jsonType, aliasMap, false);
if (getters.size() > 256) {
return null;
@@ -197,8 +201,6 @@ public class ASMSerializerFactory implements Opcodes {
"()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
mw.visitVarInsn(ASTORE, context.var("out"));
JSONType jsonType = clazz.getAnnotation(JSONType.class);
if (jsonType == null || jsonType.alphabetic()) {
Label _else = new Label();
@@ -231,7 +233,20 @@ public class ASMSerializerFactory implements Opcodes {
mw.visitEnd();
}
List<FieldInfo> sortedGetters = TypeUtils.computeGetters(clazz, aliasMap, true);
String[] orders = null;
if (jsonType != null) {
orders = jsonType.orders();
}
final List<FieldInfo> sortedGetters;
if (orders != null && orders.length != 0) {
sortedGetters = TypeUtils.computeGetters(clazz, jsonType, aliasMap, true);
} else {
sortedGetters = new ArrayList<FieldInfo>(getters);
Collections.sort(sortedGetters);
}
{
// sortField support
@@ -25,7 +25,7 @@ import com.alibaba.fastjson.util.FieldInfo;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public abstract class FieldSerializer {
public abstract class FieldSerializer implements Comparable<FieldSerializer> {
public final FieldInfo fieldInfo;
private final String double_quoted_fieldPrefix;
@@ -91,4 +91,8 @@ public abstract class FieldSerializer {
public abstract void writeProperty(JSONSerializer serializer, Object propertyValue) throws Exception;
public abstract void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception;
public int compareTo(FieldSerializer o) {
return this.fieldInfo.compareTo(o.fieldInfo);
}
}
@@ -20,12 +20,14 @@ import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.util.FieldInfo;
import com.alibaba.fastjson.util.TypeUtils;
@@ -64,10 +66,16 @@ public class JavaBeanSerializer implements ObjectSerializer {
public JavaBeanSerializer(Class<?> clazz, Map<String, String> aliasMap){
this.features = TypeUtils.getSerializeFeatures(clazz);
JSONType jsonType = clazz.getAnnotation(JSONType.class);
if (jsonType != null) {
features = SerializerFeature.of(jsonType.serialzeFeatures());
}
{
List<FieldSerializer> getterList = new ArrayList<FieldSerializer>();
List<FieldInfo> fieldInfoList = TypeUtils.computeGetters(clazz, aliasMap, false);
List<FieldInfo> fieldInfoList = TypeUtils.computeGetters(clazz, jsonType, aliasMap, false);
for (FieldInfo fieldInfo : fieldInfoList) {
getterList.add(createFieldSerializer(fieldInfo));
@@ -75,15 +83,26 @@ public class JavaBeanSerializer implements ObjectSerializer {
getters = getterList.toArray(new FieldSerializer[getterList.size()]);
}
{
List<FieldSerializer> getterList = new ArrayList<FieldSerializer>();
List<FieldInfo> fieldInfoList = TypeUtils.computeGetters(clazz, aliasMap, true);
String[] orders = null;
for (FieldInfo fieldInfo : fieldInfoList) {
getterList.add(createFieldSerializer(fieldInfo));
}
if (jsonType != null) {
orders = jsonType.orders();
}
if (orders != null && orders.length != 0) {
List<FieldInfo> fieldInfoList = TypeUtils.computeGetters(clazz, jsonType, aliasMap, true);
List<FieldSerializer> getterList = new ArrayList<FieldSerializer>();
sortedGetters = getterList.toArray(new FieldSerializer[getterList.size()]);
for (FieldInfo fieldInfo : fieldInfoList) {
getterList.add(createFieldSerializer(fieldInfo));
}
sortedGetters = getterList.toArray(new FieldSerializer[getterList.size()]);
} else {
sortedGetters = new FieldSerializer[getters.length];
System.arraycopy(getters, 0, sortedGetters, 0, getters.length);
Arrays.sort(sortedGetters);
}
}
@@ -32,7 +32,7 @@ public class ASMUtils {
return IS_ANDROID;
}
public static String getDesc(Method method) {
public static String getDesc(Method method) {
Class<?>[] types = method.getParameterTypes();
StringBuilder buf = new StringBuilder((types.length + 1) << 4);
buf.append('(');
@@ -37,13 +37,17 @@ public class DeserializeBeanInfo {
private final List<FieldInfo> sortedFieldList = new ArrayList<FieldInfo>();
private int parserFeatures = 0;
public final JSONType jsonType;
public DeserializeBeanInfo(Class<?> clazz
, Class<?> builderClass
, Constructor<?> defaultConstructor
, Constructor<?> creatorConstructor
, Method factoryMethod
, Method buildMethod){
public DeserializeBeanInfo(Class<?> clazz, //
Class<?> builderClass, //
Constructor<?> defaultConstructor, //
Constructor<?> creatorConstructor, //
Method factoryMethod, //
Method buildMethod, //
JSONType jsonType
){
this.clazz = clazz;
this.builderClass = builderClass;
this.defaultConstructor = defaultConstructor;
@@ -51,6 +55,8 @@ public class DeserializeBeanInfo {
this.factoryMethod = factoryMethod;
this.parserFeatures = TypeUtils.getParserFeatures(clazz);
this.jsonType = jsonType;
defaultConstructorParameterSize = defaultConstructor != null ? defaultConstructor.getParameterTypes().length : 0;
}
@@ -113,18 +119,23 @@ public class DeserializeBeanInfo {
public static DeserializeBeanInfo computeSetters(Class<?> clazz, Type type) {
DeserializeBeanInfo beanInfo = null;
JSONType jsonType = clazz.getAnnotation(JSONType.class);
Class<?> builderClass = getBuilderClass(clazz);
Class<?> builderClass = getBuilderClass(jsonType);
Field[] declaredFields = clazz.getDeclaredFields();
Method[] methods = clazz.getMethods();
Constructor<?> defaultConstructor = getDefaultConstructor(builderClass == null ? clazz : builderClass);
if (defaultConstructor != null) { // 如果存在默认构造方法
TypeUtils.setAccessible(defaultConstructor);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, defaultConstructor, null, null, null);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, defaultConstructor, null, null, null, jsonType);
} else if (defaultConstructor == null && !(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()))) {
Constructor<?> creatorConstructor = getCreatorConstructor(clazz);
if (creatorConstructor != null) { // 基于标记 JSONCreator 注解的构造方法
TypeUtils.setAccessible(creatorConstructor);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, creatorConstructor, null, null);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, creatorConstructor, null, null, jsonType);
Class<?>[] types = creatorConstructor.getParameterTypes();
if (types.length > 0) {
@@ -143,7 +154,7 @@ public class DeserializeBeanInfo {
}
Class<?> fieldClass = types[i];
Type fieldType = creatorConstructor.getGenericParameterTypes()[i];
Field field = TypeUtils.getField(clazz, fieldAnnotation.name());
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
final int ordinal = fieldAnnotation.ordinal();
final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field,
@@ -154,11 +165,11 @@ public class DeserializeBeanInfo {
return beanInfo;
}
Method factoryMethod = getFactoryMethod(clazz); // 基于标记 JSONCreator 注解的工厂方法
Method factoryMethod = getFactoryMethod(clazz, methods); // 基于标记 JSONCreator 注解的工厂方法
if (factoryMethod != null) {
TypeUtils.setAccessible(factoryMethod);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, null, factoryMethod, null);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, null, factoryMethod, null, jsonType);
Class<?>[] types = factoryMethod.getParameterTypes();
if (types.length > 0) {
Annotation[][] paramAnnotationArrays = factoryMethod.getParameterAnnotations();
@@ -177,7 +188,7 @@ public class DeserializeBeanInfo {
Class<?> fieldClass = types[i];
Type fieldType = factoryMethod.getGenericParameterTypes()[i];
Field field = TypeUtils.getField(clazz, fieldAnnotation.name());
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
final int ordinal = fieldAnnotation.ordinal();
final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name(), clazz, fieldClass, fieldType, field, ordinal, serialzeFeatures);
@@ -191,7 +202,7 @@ public class DeserializeBeanInfo {
}
if (beanInfo == null) {
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, null, null, null);
beanInfo = new DeserializeBeanInfo(clazz, builderClass, null, null, null, null, jsonType);
}
if (builderClass != null) {
String withPrefix = null;
@@ -300,7 +311,7 @@ public class DeserializeBeanInfo {
}
}
for (Method method : clazz.getMethods()) { //
for (Method method : methods) { //
int ordinal = 0, serialzeFeatures = 0;
String methodName = method.getName();
if (methodName.length() < 4) {
@@ -366,10 +377,10 @@ public class DeserializeBeanInfo {
continue;
}
Field field = TypeUtils.getField(clazz, propertyName);
Field field = TypeUtils.getField(clazz, propertyName, declaredFields);
if (field == null && types[0] == boolean.class) {
String isFieldName = "is" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
field = TypeUtils.getField(clazz, isFieldName);
field = TypeUtils.getField(clazz, isFieldName, declaredFields);
}
JSONField fieldAnnotation = null;
@@ -515,10 +526,10 @@ public class DeserializeBeanInfo {
return creatorConstructor;
}
public static Method getFactoryMethod(Class<?> clazz) {
private static Method getFactoryMethod(Class<?> clazz, Method[] methods) {
Method factoryMethod = null;
for (Method method : clazz.getDeclaredMethods()) {
for (Method method : methods) {
if (!Modifier.isStatic(method.getModifiers())) {
continue;
}
@@ -544,8 +555,7 @@ public class DeserializeBeanInfo {
return parserFeatures;
}
public static Class<?> getBuilderClass(Class<?> clazz) {
JSONType type = clazz.getAnnotation(JSONType.class);
public static Class<?> getBuilderClass(JSONType type) {
if (type == null) {
return null;
}
@@ -897,9 +897,7 @@ public class TypeUtils {
Map<String, FieldDeserializer> setters = mapping.getFieldDeserializers(clazz);
Constructor<T> constructor = clazz.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
constructor.setAccessible(true);
T object = constructor.newInstance();
for (Map.Entry<String, FieldDeserializer> entry : setters.entrySet()) {
@@ -1035,11 +1033,7 @@ public class TypeUtils {
return clazz;
}
public static List<FieldInfo> computeGetters(Class<?> clazz, Map<String, String> aliasMap) {
return computeGetters(clazz, aliasMap, true);
}
public static List<FieldInfo> computeGetters(Class<?> clazz, Map<String, String> aliasMap, boolean sorted) {
public static List<FieldInfo> computeGetters(Class<?> clazz, JSONType jsonType, Map<String, String> aliasMap, boolean sorted) {
Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<String, FieldInfo>();
for (Method method : clazz.getMethods()) {
@@ -1471,8 +1465,8 @@ public class TypeUtils {
return Object.class;
}
public static Field getField(Class<?> clazz, String fieldName) {
for (Field field : clazz.getDeclaredFields()) {
public static Field getField(Class<?> clazz, String fieldName, Field[] declaredFields) {
for (Field field : declaredFields) {
if (fieldName.equals(field.getName())) {
return field;
}
@@ -1480,7 +1474,7 @@ public class TypeUtils {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && superClass != Object.class) {
return getField(superClass, fieldName);
return getField(superClass, fieldName, superClass.getDeclaredFields());
}
return null;
@@ -1,15 +1,16 @@
package com.alibaba.json.test.benchmark;
import com.alibaba.json.test.benchmark.decode.EishayDecode;
import com.alibaba.json.test.codec.FastjsonCodec;
import com.alibaba.json.test.benchmark.decode.*;
import com.alibaba.json.test.benchmark.encode.*;
import com.alibaba.json.test.codec.*;
public class BenchmarkMain {
public static void main(String[] args) throws Exception {
// 注意,byte[]在jackson中是使用base64编码的,不正确的。
BenchmarkExecutor executor = new BenchmarkExecutor();
executor.setExecuteCount(5);
executor.getCodecList().add(new FastjsonCodec());
executor.setExecuteCount(3);
executor.getCodecList().add(new FastjsonSCodec());
// executor.getCodecList().add(new FastjsonGenCodec());
// executor.getCodecList().add(new FastjsonBeanToArrayCodec());
// executor.getCodecList().add(new JacksonCodec());
@@ -19,14 +20,14 @@ public class BenchmarkMain {
// executor.getCodecList().add(new JsonLibCodec());
// executor.getCodecList().add(new JsonSmartCodec());
executor.setLoopCount(1000 * 1000 * 1);
executor.setLoopCount(1000 * 1 * 1);
// executor.getCaseList().add(new EishayDecodeBytes());
// executor.getCaseList().add(new EishayDecode2Bytes());
executor.getCaseList().add(new EishayDecode());
// executor.getCaseList().add(new EishayDecodeByClassName());
// executor.getCaseList().add(new EishayTreeDecode());
// executor.getCaseList().add(new EishayEncode());
executor.getCaseList().add(new EishayEncode());
// executor.getCaseList().add(new EishayEncodeManual());
// executor.getCaseList().add(new IntArray1000Decode());
// executor.getCaseList().add(new StringArray1000Decode());
@@ -0,0 +1,74 @@
package com.alibaba.json.test.codec;
import java.util.Collection;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.DefaultExtJSONParser;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class FastjsonSCodec implements Codec {
public String getName() {
return "fastjson";
}
public <T> T decodeObject(String text, Class<T> clazz) {
ParserConfig config = new ParserConfig();
DefaultExtJSONParser parser = new DefaultExtJSONParser(text, config);
parser.config(Feature.DisableCircularReferenceDetect, true);
return parser.parseObject(clazz);
}
public <T> Collection<T> decodeArray(String text, Class<T> clazz) throws Exception {
ParserConfig config = new ParserConfig();
DefaultExtJSONParser parser = new DefaultExtJSONParser(text, config);
parser.config(Feature.DisableCircularReferenceDetect, true);
return parser.parseArray(clazz);
}
public final Object decodeObject(String text) {
ParserConfig config = new ParserConfig();
DefaultJSONParser parser = new DefaultJSONParser(text, config);
parser.config(Feature.DisableCircularReferenceDetect, true);
return parser.parse();
}
public final Object decode(String text) {
ParserConfig config = new ParserConfig();
DefaultJSONParser parser = new DefaultJSONParser(text, config);
parser.config(Feature.DisableCircularReferenceDetect, true);
return parser.parse();
}
// private JavaBeanSerializer serializer = new JavaBeanSerializer(Long_100_Entity.class);
public String encode(Object object) throws Exception {
SerializeConfig config = new SerializeConfig();
SerializeWriter out = new SerializeWriter();
out.config(SerializerFeature.DisableCircularReferenceDetect, true);
// out.config(SerializerFeature.DisableCheckSpecialChar, true);
JSONSerializer serializer = new JSONSerializer(out, config);
serializer.write(object);
String text = out.toString();
out.close();
return text;
}
@SuppressWarnings("unchecked")
public <T> T decodeObject(byte[] input, Class<T> clazz) throws Exception {
return (T) JSON.parseObject(input, clazz, Feature.DisableCircularReferenceDetect);
}
}