概述
FastJson2
是FastJson
项目的重要升级,目标是为下一个十年提供一个高性能的JSON
库。根据官方给出的性能来看,相比v1版本,确实有了很大的提升,本篇文章我们来看下究竟做了哪些事情,使得性能有了大幅度的提升。
本篇将采用代码测试
+ 源码阅读
的方式对FastJson2的性能提升做一个较为全面的探索。
一、环境准备
首先,我们搭建一套用于测试的环境,这里采用springboot项目,分别创建两个module:fastjson
和fastjson2
。使用两个版本进行对比试验。
代码结构如下所示:
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