Jackson和FastJson性能谁更快

前言

jackson和fastjson大概是我们使用得最多的两个json序列化包和反序列化包。网上的性能对比很多,大多数的结果对fastjson都不利,甚至有的结论是比Gson还要慢,但是我觉得fastjson是阿里系的,应该性能不会差,于是作了一系列对比。我们这里使用的是最新的两个包jackjson为2.8版本,而fastjson为1.2.14版本

对比使用对象

在对比中使用的对象基本包含了所有的数据类型和集合,并且是随机生成。这里我直接借鉴了别人测试的时候使用的对象,因为的确比较好,我便没有修改,代码如下:

/**
 * Created by lz on 2016/7/23.
 */
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 该类提供生成样本的元数据
 *
 */
public class DataBuilder {
    private static final String[] chars = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b",
            "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
            "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z" };

    private static final int charNum = 62;

    // 样本String最大长度
    private static final int maxStrLength = 100;

    // 样本String默认长度
    private static final int defaultStrLength = 50;

    // 样本List最大长度
    private static final int maxListSize = 100;

    // 样本List默认长度
    private static final int defaultListSize = 10;

    // 样本Map最大Key数量
    private static final int maxMapSize = 100;

    // 样本Map默认Key数量
    private static final int defaultMapSize = 10;

    // 样本Map中Value的数据类型
    private static final String[] types = new String[] { "boolean", "int", "long", "double", "date", "string"};
    private static final int typeNum = 6;

    private static final Random random = new Random();

    /**
     * 生成随机长度的字符串
     * @return 字符串
     */
    public static String randomString(){
        return randomString(random.nextInt(maxStrLength));
    }

    /**
     * 生成指定长度的字符串
     * @param len 字符串长度
     * @return
     */
    public static String randomString(int len) {
        if (len < 1 || len > maxStrLength) {
            // 如果字符串长度超出范围,使用默认长度
            len = defaultStrLength;
        }

        StringBuilder sb = new StringBuilder(len);

        for (int i = 0; i < len; i++) {
            sb.append(chars[random.nextInt(charNum)]);
        }

        return sb.toString();
    }

    /**
     * 生成List样本,List中元素的数量随机
     * @return
     */
    public static List<String> randomStringList() {
        return randomStringList(random.nextInt(maxListSize));
    }

    /**
     * 生成List样本
     * @param size List中元素的数量
     * @return
     */
    public static List<String> randomStringList(int size) {
        if (size < 1 || size > maxListSize) {
            size = defaultListSize;
        }

        List<String> list = new ArrayList<String>();

        for (int i = 0; i < size; i++) {
            list.add(randomString(random.nextInt(maxStrLength)));
        }

        return list;
    }

    /**
     * 生成随机Map样本,样本中key的数量随机
     * @return
     */
    public static Map<String, Object> randomMap() {
        return randomMap(random.nextInt(maxMapSize));
    }

    /**
     * 生成随机Map样本
     * @param size 样本中key的数量
     * @return
     */
    public static Map<String, Object> randomMap(int size) {
        if (size < 1 || size > maxMapSize) {
            size = defaultMapSize;
        }

        Map<String, Object> map = new HashMap<String, Object>();

        for (int i = 0; i < size; i++) {
            String type = types[random.nextInt(typeNum)];
            if ("boolean".equals(type)) {
                map.put("key" + i, random.nextBoolean());
            } else if ("int".equals(type)) {
                map.put("key" + i, random.nextInt());
            } else if ("long".equals(type)) {
                map.put("key" + i, random.nextLong());
            } else if ("double".equals(type)) {
                map.put("key" + i, random.nextDouble());
            } else if ("date".equals(type)) {
                map.put("key" + i, new Date());
            } else if ("string".equals(type)) {
                map.put("key" + i, randomString(random.nextInt(maxStrLength)));
            }
        }

        return map;
    }
}

以及

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 样本对象
 *
 */
public class JsonObject implements Serializable {
    private static final long serialVersionUID = -1520171788566678009L;

    private Boolean fieldBoolean;
    private Integer fieldInt;
    private Long fieldLong;
    private Double fieldDouble;
    private Date fieldDate;
    private String fieldStr;
    private List<String> fieldList;
    private Map<String, Object> fieldMap;

    /**
     * 随机样本
     */
    public JsonObject() {
        Random random = new Random();

        fieldBoolean = random.nextBoolean();
        fieldInt = random.nextInt();
        fieldLong = random.nextLong();
        fieldDouble = random.nextDouble();
        fieldDate = new Date();
        fieldStr = DataBuilder.randomString();

        fieldList = DataBuilder.randomStringList();

        fieldMap = DataBuilder.randomMap();
    }

    /**
     * 指定List元素数量和Map元素数量的样本
     * @param listSize List元素数量
     * @param mapKeyNum Map元素数量
     */
    public JsonObject(int listSize, int mapKeyNum) {
        Random random = new Random();

        fieldBoolean = random.nextBoolean();
        fieldInt = random.nextInt();
        fieldLong = random.nextLong();
        fieldDouble = random.nextDouble();
        fieldDate = new Date();
        fieldStr = DataBuilder.randomString();

        fieldList = DataBuilder.randomStringList(listSize);

        fieldMap = DataBuilder.randomMap(mapKeyNum);
    }

    public Boolean getFieldBoolean() {
        return fieldBoolean;
    }

    public void setFieldBoolean(Boolean fieldBoolean) {
        this.fieldBoolean = fieldBoolean;
    }

    public Integer getFieldInt() {
        return fieldInt;
    }

    public void setFieldInt(Integer fieldInt) {
        this.fieldInt = fieldInt;
    }

    public Long getFieldLong() {
        return fieldLong;
    }

    public void setFieldLong(Long fieldLong) {
        this.fieldLong = fieldLong;
    }

    public Double getFieldDouble() {
        return fieldDouble;
    }

    public void setFieldDouble(Double fieldDouble) {
        this.fieldDouble = fieldDouble;
    }

    public Date getFieldDate() {
        return fieldDate;
    }

    public void setFieldDate(Date fieldDate) {
        this.fieldDate = fieldDate;
    }

    public String getFieldStr() {
        return fieldStr;
    }

    public void setFieldStr(String fieldStr) {
        this.fieldStr = fieldStr;
    }

    public List<String> getFieldList() {
        return fieldList;
    }

    public void setFieldList(List<String> fieldList) {
        this.fieldList = fieldList;
    }

    public Map<String, Object> getFieldMap() {
        return fieldMap;
    }

    public void setFieldMap(Map<String, Object> fieldMap) {
        this.fieldMap = fieldMap;
    }

}

测试方法

我们的测试策略如下:

输入需要测试的个数,例如输入10000,然后会对此进行测试10次,按照国际惯例去掉时间最小的,和一个时间最大的,剩下的8次再来求平均值,得到的就是我们所要求得平均速度,这里我们需要测试10个数据 1000个数据 10万个数据。代码如下:

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 测试方法
 * 输入需要测试的个数
 * 例如输入10000
 * 然后会对此进行测试10次,去掉时间最小的,和一个时间最大的,剩下的8次再来求平均值
 * 得到的就是我们所要求得平均速度
 * 这里我们需要测试10个数据 1000个数据 10万个数据
 * Created by lz on 2016/7/24.
 */
public class TestMain {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 传入数据的个数
     * @param nums
     * @return
     */
    public static List<Double> complete(int nums) throws Exception {
        Double[] jacksonTimes = new Double[10];
        Double[] fastjsonTimes = new  Double[10];
        Double[] jacksonTimes1 = new Double[10];
        Double[] fastjsonTimes1 = new  Double[10];
        List<Double> time = new ArrayList<Double>();
        for (int i = 0; i < 10 ; i++) {
            List<Double> list = getTime(nums);
            jacksonTimes[i]=list.get(0);
            fastjsonTimes[i]=list.get(1);
            jacksonTimes1[i]=list.get(2);
            fastjsonTimes1[i]=list.get(3);
        }
        Arrays.sort(jacksonTimes);
        Arrays.sort(fastjsonTimes);
        Arrays.sort(jacksonTimes1);
        Arrays.sort(fastjsonTimes1);
        Double sum = 0.00;
        for (int i = 1; i < 9; i++) {
            sum += jacksonTimes[i];
        }
        time.add(sum/8);
        sum=0.00;
        for (int i = 1; i < 9; i++) {
            sum += fastjsonTimes[i];
        }
        time.add(sum/8);
        sum=0.00;
        for (int i = 1; i < 9; i++) {
            sum += jacksonTimes1[i];
        }
        time.add(sum/8);
        sum=0.00;
        for (int i = 1; i < 9; i++) {
            sum += fastjsonTimes1[i];
        }
        time.add(sum/8);
        return time;
    }

    /**
     * 传入数据的个数
     * @param nums
     * @return list.get(0)是jackson本次的时间 list.get(1)是fastjson本次的时间
     */
    public static List<Double> getTime(int nums) throws Exception {
        Double jacksonTime1 = 0.00;
        Double fastjsonTime1 = 0.00;
        Double jacksonTime2 = 0.00;
        Double fastjsonTime2 = 0.00;
        for (int i = 0; i < nums; i++) {
             //这里我们生成jsonObject
            JsonObject  jsonObject = new JsonObject();
            long start,end;
            String str = null;
            start = System.currentTimeMillis();
            str = OBJECT_MAPPER.writeValueAsString(jsonObject);
            end = System.currentTimeMillis();
            jacksonTime1 += Double.valueOf(end-start);
            start = System.currentTimeMillis();
            str = JSON.toJSONString(jsonObject);
            end = System.currentTimeMillis();
            fastjsonTime1 += Double.valueOf(end-start);
            start = System.currentTimeMillis();
            OBJECT_MAPPER.readValue(str, JsonObject.class);
            end = System.currentTimeMillis();
            jacksonTime2 += Double.valueOf(end-start);
            start = System.currentTimeMillis();
            JSON.parseObject(str,JsonObject.class);
            end = System.currentTimeMillis();
            fastjsonTime2 += Double.valueOf(end-start);
        }
        List<Double> list = new ArrayList<Double>();
        list.add(jacksonTime1);
        list.add(fastjsonTime1);
        list.add(jacksonTime2);
        list.add(fastjsonTime2);
        return list;
    }
    public static void main(String[] args) throws Exception {
        //输入测试个数,得到时间
        List<Double> list10 = complete(10);
        List<Double> list1000 = complete(1000);
        List<Double> list100000 = complete(100000);
        System.out.println("------------------------序列化时间比较----------------------------");
        System.out.println("测试数据为10的时候:jackson序列化时间:"+list10.get(0)+"ms | fastjson序列化时间"+list10.get(1)+"ms");
        System.out.println("测试数据为1000的时候:jackson序列化时间:"+list1000.get(0)+"ms | fastjson序列化时间"+list1000.get(1)+"ms");
        System.out.println("测试数据为100000的时候:jackson序列化时间:"+list100000.get(0)+"ms | fastjson序列化时间"+list100000.get(1)+"ms");
        System.out.println("------------------------反序列化时间比较----------------------------");
        System.out.println("测试数据为10的时候:jackson反序列化时间:"+list10.get(2)+"ms | fastjson反序列化时间"+list10.get(3)+"ms");
        System.out.println("测试数据为1000的时候:jackson反序列化时间:"+list1000.get(2)+"ms | fastjson反序列化时间"+list1000.get(3)+"ms");
        System.out.println("测试数据为100000的时候:jackson反序列化时间:"+list100000.get(2)+"ms | fastjson反序列化时间"+list100000.get(3)+"ms");
    }
}

最后的结果:

————————序列化时间比较—————————-

测试数据为10的时候:jackson序列化时间:5.0ms | fastjson序列化时间4.75ms

测试数据为1000的时候:jackson序列化时间:61.375ms | fastjson序列化时间45.875ms

测试数据为100000的时候:jackson序列化时间:2448.875ms | fastjson序列化时间2421.375ms

————————反序列化时间比较—————————-

测试数据为10的时候:jackson反序列化时间:13.0ms | fastjson反序列化时间9.25ms

测试数据为1000的时候:jackson反序列化时间:148.375ms | fastjson反序列化时间133.625ms

测试数据为100000的时候:jackson反序列化时间:9488.625ms | fastjson反序列化时间9356.75ms

结论

有时候,别人做的东西还真的不能信,必须要自己亲身体验测试过才知道速度的快慢,fastjson并不是像很多人说的速度要慢很多,基本序列化时间和反序列化时间都是55开的甚至fastjson可能要略胜与jackson。

github地址:https://github.com/lzggsimida123/json1

时间: 2024-10-19 01:17:29

Jackson和FastJson性能谁更快的相关文章

《Java程序性能优化:让你的Java程序更快、更稳定》

Java程序性能优化:让你的Java程序更快.更稳定, 卓越网更便宜,不错的书吧

SQL查询性能调优--如何使查询更快

翻译自https://mode.com/sql-tutorial/sql-performance-tuning 从这儿开始吗?这篇是使用SQL进行数据分析教程的一部分,查看教程开始. 子查询那一课让我们意识到可以通过运行更快到语句得到同样到结果集.在这节课中,你会学习识别查询优化点,以及如何优化. 查询时间背后的理论 数据库也是一个运行在计算机上的软件,像所有的软件一样,运行速度囿于相同的“天花板”——它的硬件所能处理的最大信息量也就是它所能处理的最大信息量.使一个查询运行更快的方法就是减少软件

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

探寻C/C++中更快的大数(自然数集)模板

本文系fcbruce个人原创整理,转载请注明出处http://blog.csdn.net/u012965890/article/details/40432511,谢谢! 我们知道在C/C++中int型可处理-2^31~2^31-1(32位及以上编译器),long long型可处理-2^63~2^63-1的数据,这实际上是非常有限的,在很多情况下,我们往往会处理范围更大的数据.Java中有BigInteger类,python中想要多大就有多大(取决于内存),但是C/C++就显得有些乏力,这时候我们

PHP 更快的方式实现数组去重

概述 使用PHP的array_unique()函数允许你传递一个数组,然后移除重复的值,返回一个拥有唯一值的数组.这个函数大多数情况下都能工作得很好.但是,如果你尝试在一个大的数组里使用array_unique()函数,它会运行地慢一些. 有一个比较好而且更快的函数array_flip()来替代使用array_unique()函数来创建唯一的数组.这个魔法般的函数会交换数组里面每一个元素的键和值,因为键值必须唯一,因此,你会得到跟array_unique()函数一样的结果. 更快的方式实现PHP

简单的几步让你的JQuery跑得更快

本文提供即刻提升你的脚本性能的十个步骤.不用担心,这并不是什么高深的技巧.人人皆可运用!这些技巧包括: 使用最新版本永盈会娱乐城 合并.最小化脚本 用for替代each 用ID替代class选择器 给选择器指定前后文 建立缓存 避免DOM操作 避免使用concat(),利用join()处理长字串 返回false值 利用小抄和参考文档 使用最新版本 jQuery一直处于不断的开发和改进过程中. John 和他的团队不断研究着提升程序性能的新方法. 一点题外话,几个月前他还发布了Sizzle,一个据

CSS VS JS动画,哪个更快[译]

英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js动画库.在<Javascript网页动画设计>一书中对这个库有很多更具体的剖析,对Velocity及JS动画感兴趣的可以一看. 基于Javascript的动画怎么可能总是和 CSS transition 一样快,甚至更快呢?到底是什么秘密呢?Adobe 和 Google 是怎么做到让他们的富媒体移

使用tar+lz4/pigz+ssh更快的数据传输

使用tar+lz4/pigz+ssh更快的数据传输 2013-11-8 | 10:41分类:Linux,MySQL | 前面一篇介绍了如何最大限度的榨取SCP的传输速度,有了这个基础,就可以进一步的使用压缩来加速传输速度了.只使用scp,传输速率最快约90MB,本文通过压缩将把最快传输速率提升到约250MB/s(包括解压的过程). 目录 [hide] 1. 结论 2. 关于lz4 3. 性能环境说明 3.1 磁盘读取和落盘 3.2 打包.拆包 3.3 压缩.解压缩 3.4 传输 3.5 整体流程

更轻更快的Vue.js 2.0与其他框架对比(转)

更轻更快的Vue.js 2.0 崭露头角的JavaScript框架Vue.js 2.0版本已经发布,在狂热的JavaScript世界里带来了让人耳目一新的变化. Vue创建者尤雨溪称,Vue 2.0 在性能上有显著的提升,同时保持轻量的文件下载: 渲染层基于一个轻量级的Virtual DOM实现进行了重写,该Virtual DOM实现fork自snabbdom.新的渲染层相比v1带来了巨大的性能提升,也让Vue 2.0成为了最快速的框架之一. 根据1.0到2.0迁移指南,“大约90%的API是相