【性能优化】GSON解性能瓶颈分析

一、背景

    GSON是Google提供的开源库,使用很便捷,但是在使用过程中也发现了其短板。在Bean类结构复杂时,进行反序列化耗时较长,尤其是很多在应用启动阶段需要反序列化一些内置的数据时,很让人头疼,通过抓Trace能发现这个性能问题。
    注:本文基于Gson2.8.5分析(implementation ‘com.google.code.gson:gson:2.8.5’)

二、反序列化为什么耗时分析?

2.1 抛出问题:gson反序列化过程火焰图

GSON反序列化火焰图
如上图GSON解析过程可以看出,在反序列化过程中使用了大量反射导致耗时较长
在这里插入图片描述
json结构:

{
  "name":"zhang",
  "age":33,
  "sex":1,
  "bestStudent":{
    "name":"san",
    "age":10,
    "sex":1,
    "grade":1,
    "favoriteSubject":{
      "subjectName":"music",
      "subjectScore":90.1
    },
    "subjects":[
      {
        "subjectName":"music",
        "subjectScore":90.1
      },
      {
        "subjectName":"literature",
        "subjectScore":80.1
      },
      {
        "subjectName":"mathematics",
        "subjectScore":70.1
      }
    ]
  },
  "students":[
    {
      "name":"li",
      "age":10,
      "sex":1,
      "grade":1,
      "favoriteSubject":{
        "subjectName":"music",
        "subjectScore":90.1
      },
      "subjects":[
        {
          "subjectName":"music",
          "subjectScore":90.1
        },
        {
          "subjectName":"literature",
          "subjectScore":80.1
        },
        {
          "subjectName":"mathematics",
          "subjectScore":70.1
        }
      ]
    },
    {
      "name":"wang",
      "age":10,
      "sex":1,
      "grade":1,
      "favoriteSubject":{
        "subjectName":"literature",
        "subjectScore":80.1
      },
      "subjects":[
        {
          "subjectName":"music",
          "subjectScore":90.1
        },
        {
          "subjectName":"literature",
          "subjectScore":80.1
        },
        {
          "subjectName":"mathematics",
          "subjectScore":70.1
        }
      ]
    },
    {
      "name":"zhou",
      "age":10,
      "sex":1,
      "grade":1,
      "favoriteSubject":{
        "subjectName":"music",
        "subjectScore":90.1
      },
      "subjects":[
        {
          "subjectName":"music",
          "subjectScore":90.1
        },
        {
          "subjectName":"literature",
          "subjectScore":80.1
        },
        {
          "subjectName":"mathematics",
          "subjectScore":70.1
        }
      ]
    }
  ]

}
2.2 Gson是怎么做反序列化的?
2.2.1 先看Gson构造函数,默认构造函数走到下面这个实现:
  Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
      int timeStyle, List<TypeAdapterFactory> builderFactories,
      List<TypeAdapterFactory> builderHierarchyFactories,
      List<TypeAdapterFactory> factoriesToBeAdded) {
    this.excluder = excluder;
    this.fieldNamingStrategy = fieldNamingStrategy;
    this.instanceCreators = instanceCreators;
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
    this.serializeNulls = serializeNulls;
    this.complexMapKeySerialization = complexMapKeySerialization;
    this.generateNonExecutableJson = generateNonExecutableGson;
    this.htmlSafe = htmlSafe;
    this.prettyPrinting = prettyPrinting;
    this.lenient = lenient;
    this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
    this.longSerializationPolicy = longSerializationPolicy;
    this.datePattern = datePattern;
    this.dateStyle = dateStyle;
    this.timeStyle = timeStyle;
    this.builderFactories = builderFactories;
    this.builderHierarchyFactories = builderHierarchyFactories;
	// (1)
    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

    // built-in type adapters that cannot be overridden
    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
    factories.add(ObjectTypeAdapter.FACTORY);

    // the excluder must precede all adapters that handle user-defined types
    factories.add(excluder);

    // users' type adapters
    factories.addAll(factoriesToBeAdded);

    // type adapters for basic platform types
    factories.add(TypeAdapters.STRING_FACTORY);
    factories.add(TypeAdapters.INTEGER_FACTORY);
    factories.add(TypeAdapters.BOOLEAN_FACTORY);
    factories.add(TypeAdapters.BYTE_FACTORY);
    factories.add(TypeAdapters.SHORT_FACTORY);
    TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
    factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
    factories.add(TypeAdapters.newFactory(double.class, Double.class,
            doubleAdapter(serializeSpecialFloatingPointValues)));
    factories.add(TypeAdapters.newFactory(float.class, Float.class,
            floatAdapter(serializeSpecialFloatingPointValues)));
    factories.add(TypeAdapters.NUMBER_FACTORY);
    factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
    factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
    factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
    factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
    factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
    factories.add(TypeAdapters.CHARACTER_FACTORY);
    factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
    factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
    factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
    factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
    factories.add(TypeAdapters.URL_FACTORY);
    factories.add(TypeAdapters.URI_FACTORY);
    factories.add(TypeAdapters.UUID_FACTORY);
    factories.add(TypeAdapters.CURRENCY_FACTORY);
    factories.add(TypeAdapters.LOCALE_FACTORY);
    factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
    factories.add(TypeAdapters.BIT_SET_FACTORY);
    factories.add(DateTypeAdapter.FACTORY);
    factories.add(TypeAdapters.CALENDAR_FACTORY);
    factories.add(TimeTypeAdapter.FACTORY);
    factories.add(SqlDateTypeAdapter.FACTORY);
    factories.add(TypeAdapters.TIMESTAMP_FACTORY);
    factories.add(ArrayTypeAdapter.FACTORY);
    factories.add(TypeAdapters.CLASS_FACTORY);

    // type adapters for composite and user-defined types
    factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
    factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
    this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
    factories.add(jsonAdapterFactory);
    factories.add(TypeAdapters.ENUM_FACTORY);
    // (2)对业务Bean类的反序列化主要就是靠此TypeAdapterFactory创建的TypeAdapter实现的
    factories.add(new ReflectiveTypeAdapterFactory(
        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));

    this.factories = Collections.unmodifiableList(factories);
  }
  • (1) 为了解析json字符串,针对不同类型的节点,使用了不同的TypeAdapterFactory
  • (2) 对业务Bean类的反序列化主要就是靠ReflectiveTypeAdapterFactory创建的TypeAdapter实现的,也正是这个TypeAdapter构造的TypeAdapter使用了反射给目标bean字段赋值。
2.2.2 TypeAdapter的作用
public abstract class TypeAdapter<T> {
	// 为 value写入一个 JSON 值(数组、对象、字符串、数字、布尔值或 null)。
	public abstract void write(JsonWriter out, T value) throws IOException;
	// 读取一个 JSON 值(数组、对象、字符串、数字、布尔值或 null)并将其转换为 Java 对象。返回转换后的对象。
	public abstract T read(JsonReader in) throws IOException;
}

如上所示,TypeAdapter主要定义了供子类实现的write和read方法。

参考文章

【1】抖音 Android 性能优化系列:启动优化实践

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于OpenFeign的性能优化,可以考虑以下几个方面: 1. 合理使用连接池:OpenFeign默认使用了Apache HttpClient作为HTTP客户端,可以通过配置连接池来提高性能。可以增加`maxConnections`和`maxConnectionsPerRoute`参数来调整连接池大小,以适应并发请求。 2. 启用GZIP压缩:OpenFeign支持请求和响应的GZIP压缩,可以通过设置`Content-Encoding`和`Accept-Encoding`头来启用压缩。这样可以减少网络传输的数据量,提高性能。 3. 避免重复解析:OpenFeign默认使用Jackson进行JSON解析,可以通过使用更高效的解析库如Fastjson或Gson来减少解析时间。 4. 启用请求/响应日志:通过启用请求和响应的日志,可以帮助我们定位潜在的性能问题。可以通过设置`logging.level.<package>.<class>=DEBUG`来启用详细的日志输出。 5. 设置超时时间:根据实际需求,合理设置连接超时和读取超时时间,避免长时间的阻塞。 6. 缓存策略:对于一些不经常变化的数据,可以考虑使用缓存来减少对后端服务的请求。可以使用框架如Redis或Guava来实现缓存。 7. 并发控制:如果需要同时发起多个请求,可以使用并发控制机制如信号量或线程池来限制并发数量,避免过多的请求导致性能下降。 需要注意的是,性能优化是一个综合考虑的过程,需要根据具体的业务场景和需求进行调整和优化。以上只是一些常见的优化措施,具体还需要根据实际情况进行进一步的分析和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechMix

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值