Fastjson2你有开始使用吗?快来看看源码解析

本文通过对Fastjson2的性能测试和源码分析,揭示了其性能提升的关键因素。测试结果显示,Fastjson2的性能提升与堆内存大小密切相关,小内存环境下其性能不如Fastjson。源码分析涉及序列化writer和反序列化reader,揭示了Fastjson2利用ASM动态字节码技术实现数据写入和读取。然而,Fastjson2在内存管理和兼容性方面存在问题,官方Issue较多,源码阅读难度大。
摘要由CSDN通过智能技术生成

概述

FastJson2FastJson项目的重要升级,目标是为下一个十年提供一个高性能的JSON库。根据官方给出的性能来看,相比v1版本,确实有了很大的提升,本篇文章我们来看下究竟做了哪些事情,使得性能有了大幅度的提升。

本篇将采用代码测试 + 源码阅读的方式对FastJson2的性能提升做一个较为全面的探索。

一、环境准备

首先,我们搭建一套用于测试的环境,这里采用springboot项目,分别创建两个module:fastjsonfastjson2。使用两个版本进行对比试验。

代码结构如下所示:

1.1 引入对应依赖

在父pom当中引入一些我们需要使用的公共依赖,这里为了简便,使用了

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>
复制代码

在fastjson当中引入fastjson的依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.79</version>
</dependency>
复制代码

在fastjson2当中引入fastjson2的依赖:

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.8</version>
</dependency>
复制代码

1.2 创建测试类

这里为了方便,直接使用main方法进行测试。

  • 创建类:Student.java

    import lombok.Builder;
    import lombok.Data;
    
    @Data
    @Builder
    public class Student {
        private String name;
        private Integer age;
        private String address;
    
        public Student(String name, Integer age, String address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    }
    复制代码
  • 创建测试main方法:

    /**
    * 定义循环次数
    */
    private final static Integer NUM = 100;
    
    public static void main(String[] args) {
       // 总时间
       long totalTime = 0L;
       //初始化学生数据
       List<Student> studentList = new ArrayList<>();
       // 10w学生
       for (int i = 0; i < 100000; i++) {
           studentList.add(Student.builder().name("我犟不过你").age(10).address("黑龙江省哈尔滨市南方区哈尔滨大街267号").build());
       }
       // 按指定次数循环
       for (int i = 0; i < NUM; i++) {
           // 单次循环开始时间
           long startTime = System.currentTimeMillis();
           // 遍历学生数据
           studentList.forEach(student -> {
               // 序列化
               String s = JSONObject.toJSONString(student);
               //字符串转回java对象
               JSONObject.parseObject(s, Student.class);
           });
           // 将学生list序列化,之后转为jsonArray
           JSONArray jsonArray = JSONArray.parseArray(JSONObject.toJSONString(studentList));
           // 将jsonArray转java对象list
           jsonArray.toJavaList(Student.class);
           //单次处理时间
           long endTime = System.currentTimeMillis();
           // 单次耗时
           totalTime += (endTime - startTime);
           System.out.println("单次耗费时间:" + (endTime - startTime) + "ms");
       }
       System.out.println("平均耗费时间:" + totalTime / NUM + "ms");
    }
    复制代码

    上述代码在fastjson和fastjson2的测试中基本相同,唯一不同在于在fastjson2当中,jsonArray.toJavaList方法转变成了jsonArray.toList

二、性能测试

本节将使用上面的代码进行测试。在此之前,我们首先需要针对两个子工程设置相同的堆空间大小128M,以免造成偏差:

2.1 第一次测试

下面正是开始测试:

  • fastjson结果

    单次耗费时间:863ms
    单次耗费时间:444ms
    单次耗费时间:424ms
    单次耗费时间:399ms
    单次耗费时间:384ms
    单次耗费时间:355ms
    单次耗费时间:353ms
    单次耗费时间:363ms
    ... ...
    单次耗费时间:361ms
    单次耗费时间:356ms
    单次耗费时间:355ms
    单次耗费时间:357ms
    单次耗费时间:351ms
    单次耗费时间:354ms
    平均耗费时间:366ms
    复制代码

    如上所示,除了第一次很慢,第二次变快,到最后基本稳定在360毫秒左右,最终的平均耗时是366ms

  • fastjson2结果

    单次耗费时间:957ms
    单次耗费时间:803ms
    单次耗费时间:468ms
    单次耗费时间:435ms
    单次耗费时间:622ms
    单次耗费时间:409ms
    单次耗费时间:430ms
    ··· ···
    单次耗费时间:400ms
    单次耗费时间:641ms
    单次耗费时间:403ms
    单次耗费时间:398ms
    单次耗费时间:431ms
    单次耗费时间:356ms
    单次耗费时间:362ms
    单次耗费时间:626ms
    单次耗费时间:404ms
    单次耗费时间:395ms
    平均耗费时间:478ms
    复制代码

    如上所示,首次执行慢,逐步变快,但是后面就出现问题了,怎么执行的时间这么不稳定?跨度从390多到640多?这是怎么回事?平均时间也达到了478ms,反而比fastjson还要慢。

2.2 fastjson2慢的原因?

比较熟悉java的应该都能想到一个问题:由于堆空间大小不够,导致频繁发生GC,最终导致处理时间增长?

带着这个推测,我们使用jvisualVM来看下在fastjson2执行时,内存的使用情况,使用如下方式启动:

如上所示的启动放肆会直接打开jvis

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值