【性能优化】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 性能优化系列:启动优化实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/328477.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学生云服务器_学生云主机_学生云数据库_云+校园特惠套餐

腾讯云学生服务器优惠活动&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置112元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G3M公网带宽配置842.4元一年&#xff0c;腾讯云服务器网txyfwq.com分享…

力扣电话号码的组合

文章目录 题目说明做题思路代码实现代码解析 题目链接 题目说明 首先我们先分析一下这个题目题目中说呢先给出一个字符串这个字符串其实就是这个九键数字我们要按照要求将数字所代表的字符进行自由组合形成一个字符串并且这个字符串的长度和输入的数字字符串长度相同&#xff0…

element-ui tree树形结构全选、取消全选,展开收起

控制树形结构全选、取消全选&#xff0c;展开收起 <template><div><!-- 添加 ref"tree" 属性--><el-tree:data"data"show-checkboxdefault-expand-allnode-key"id"ref"tree"highlight-current:props"defa…

使用Python操纵Word自动编写离职报告

目录 一、背景介绍 二、技术原理 三、实现步骤 1、安装python-docx库 2、创建Word文档 3、添加标题和内容 4、添加表格和图片 5、设置样式和格式化文本 6、保存文档 四、注意事项与建议 总结 随着现代社会的发展&#xff0c;自动化和智能化已经成为各行各业追求的目…

Pytorch各种Dropout层应用于详解

目录 torch框架Dropout functions详解 dropout 用途 用法 使用技巧 参数 数学理论公式 代码示例 alpha_dropout 用途 用法 使用技巧 参数 数学理论公式 代码示例 feature_alpha_dropout 用途 用法 使用技巧 参数 数学理论 代码示例 dropout1d 用途 用…

每日一记:一个windows的bat脚本工具集

最近在工作上遇到要校验文件的问题&#xff0c;例如&#xff0c;下载了一个文件之后&#xff0c;通过查看文件的md5来校验文件是否完整&#xff0c;这个动作在linux上很简单&#xff0c;但在windows上也不难&#xff0c;可以通过 certutil 命令实现&#xff0c;该命令通常可用于…

vue流程图

效果图 组件 <template><div class="processBox" v-if="list.length"><div class="childs"><div class="child" v-for="(item,index) in list" :key="item.id +-child-+index"><div…

指定Top名校|管理学教师拜师香港理工大学院士麾下访学

X老师拟自费赴香港访学&#xff0c;并指定了香港Top5之内的高校。申请一个月后&#xff0c;我们落实了香港理工大学的访学职位&#xff0c;导师为香港工程科学院和国际系统与控制科学院的两院院士、讲座教授。 X老师背景&#xff1a; 申请类型&#xff1a;自费访问学者 工作背…

迷你洗衣机哪个牌子好用?家用小型洗衣机推荐

迷你洗衣机主要分为立式洗衣机、壁挂式洗衣机&#xff0c;在特定的情况下是能够为用户提供一定的方便的。就好比如说宝宝的衣物需要和大人的分开洗&#xff0c;或者我们日常都所要清洗内衣裤、袜子等等这些贴身的衣物&#xff0c;直接将这些小件的衣物放进到迷你洗衣机中分类单…

2024“华数杯”国际赛(B题ICM)|光伏发电|国际大学生数学建模竞赛建模解析,小鹿学长带队指引全代码文章与思路

我是小鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 完整内容可以在文章末尾领取&#xff01; 问题重述 这个问题涉及创建一个数学模型&#xff0c;以解决与光伏发电和中国电力供应相关的各个方面。 电…

计算机网络-甘晴void学习笔记

计算机网络 计科210X 甘晴void 202108010XXX 文章目录 计算机网络期中复习1计算机网络和因特网1.1 因特网1.2 网络边缘1.3 网络核心1.4 分组交换的时延/丢包和吞吐量1.5 协议层次与服务模型 2 应用层原理2.1 应用层协议原理2.2 Web和Http2.3 因特网中的电子邮件2.4 DNS&#x…

史星海先生入选 2024中英双语版《世界名人录》【综合22卷·文化卷】(中国)

史星海(中国) Shi Xinghai (China) 经海内外各界名人及世界相关权威文化机构的大力举荐&#xff0c;鉴于史星海先生在国内外文艺&#xff0c;经济&#xff0c;政治等领域的重大影响力&#xff0c;荣幸获得入编大型人物辞书2024中英双语版《世界名人录》&#xff08;综合卷文化…

Open CASCADE学习|显示模型

目录 1、编写代码 Viewer.h Viewer.cpp ViewerInteractor.h ViewerInteractor.cpp helloworld.cpp 2、配置 3、编译运行 1、编写代码 Viewer.h #pragma once ​ #ifdef _WIN32 #include <Windows.h> #endif ​ // Local includes #include "ViewerInteract…

各省快递量数据, shp+excel,2001-2021年,已实现数据可视化

基本信息. 数据名称: 各省快递量数据 数据格式: shpexcel 数据时间&#xff1a;2001-2021年 数据几何类型: 面 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1a_2001快递量/万件_2001年2a_2002快递量/万件_2002年3…

热压机PLC数据采集远程监控物联网解决方案

热压机PLC数据采集远程监控物联网解决方案 随着工业4.0时代的到来&#xff0c;智能制造已经成为制造业发展的重要方向。在热压机领域&#xff0c;PLC数据采集远程监控物联网解决方案为提高生产效率、降低维护成本、优化生产工艺提供了有效的手段。 一、热压机PLC数据采集远程…

一文带你揭秘淘宝终端技术

作者&#xff1a;周杰&#xff08;寻弦&#xff09; 在这个数字化迅速发展的时代&#xff0c;技术的每一次飞跃都不仅仅意味着一个产品的升级&#xff0c;更是对未来世界的一次大胆想象。从 PC 到 iPhone&#xff0c;从 Model 3 到 ChatGPT&#xff0c;都引领了全新的一个行业。…

Linux miniGUI移植分析

框架介绍 常用GUI程序对比 https://www.cnblogs.com/zyly/p/17378659.html MiniGUI分为底层的GAL&#xff08;图形抽象层&#xff09;和IAL&#xff08;输入抽象层&#xff09;&#xff0c;向上为基于标准POSIX接口中pthread库的Mini-Thread架构和基于Server/Client的Mini-L…

护眼灯有没有护眼的效果啊?有效果的护眼灯推荐

近几年&#xff0c;青少年近视人数呈现猛增的势头&#xff0c;且低龄化趋势也越来越明显&#xff0c;社会各界开始重视对青少年视力问题的关注。伤害视力的原因有很多种&#xff0c;其中没有良好的光线条件是问题之一&#xff0c;当使用的台灯不合格&#xff0c;频闪与蓝光问题…

渗透测试(12)- WireShark 网络数据包分析

目录 1、WireShack 简介 2、WireShark 基本使用方法 3、 WireShack 抓包分析 3.1 Hypertext Transfer Protocol (应用层) 3.2 Transmission Control Protocol (传输层) 3.3 Internet Protocol Version 4(网络层) 3.4 Ethernet Il (链路层): 数据链路层以太网头部信息 …

ZooKeeper 实战(五) Curator实现分布式锁

文章目录 ZooKeeper 实战(五) Curator实现分布式锁1.简介1.1.分布式锁概念1.2.Curator 分布式锁的实现方式1.3.分布式锁接口 2.准备工作3.分布式可重入锁3.1.锁对象3.2.非重入式抢占锁测试代码输出日志 3.3.重入式抢占锁测试代码输出日志 4.分布式非可重入锁4.1.锁对象4.2.重入…