fastjson与jackson的性能比较
本文仅作客观比较fastjson与jackson的性能测试,部分测试代码引自http://www.oschina.net/code/snippet_1156226_26432#44097 文中的方法,但是纠正了对于jackson的使用方式(需要写成单例先初始化,不要每次都new)。分别测试序列化1000,1万与10万次数据所花费的时间。
当然在此,如果大家发现文中的使用错误,也希望随时指出来帮助大家将优化做的更好。
测试代码均使用最新的jar包,而具体版本如下:
Jackson 2.x:
(这里仅测试Jackson2.x因为和1.x相比还是有些变化的,从包名就可以发现2.x变成com.fasterxml.jackson而不是1.x的org.codehaus.jackson希望大家注意区分)
jackson-annotations-2.4.1.jar
jackson-core-2.4.1.jar
jackson-databind-2.4.1.jar
fastjson
fastjson-1.1.41.jar
======================================================
------------------------------------以下为测试结果------------------------------
======================================================
预置条件1:循环1000次。
============序列化===========
序列化生成数据所用时间(秒):0.12
序列化Jackson所用时间(秒):0.077
序列化fastjson所用时间(秒):0.07
===========反序列化===========
反序列化生成数据所用时间(秒):0.095
反序列化Jackson所用时间(秒):0.114
反序列化fastjson所用时间(秒):0.149
-------------------------------------------------------------------------------------
预置条件2:循环10000次。
============序列化===========
序列化生成数据所用时间(秒):0.289
序列化Jackson所用时间(秒):0.281
序列化fastjson所用时间(秒):0.277
===========反序列化===========
反序列化生成数据所用时间(秒):0.344
反序列化Jackson所用时间(秒):0.416
反序列化fastjson所用时间(秒):0.445
-------------------------------------------------------------------------------------
预置条件3:循环100000次。
============序列化===========
序列化生成数据所用时间(秒):1.99
序列化Jackson所用时间(秒):0.855
序列化fastjson所用时间(秒):1.774
===========反序列化===========
反序列化生成数据所用时间(秒):2.69
反序列化Jackson所用时间(秒):1.33
反序列化fastjson所用时间(秒):1.606
以上对于10万条数据的测试可以看出jackson2.x在序列化上确实显现出了一些优势。
以下附代码(并附件打包):
/** * 主测试类 */ package com.test; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.core.JsonProcessingException; /** * * @author guoyongxiang * Date: 2014-8-20 */ public class JsonParseTest { public static void main(String[] args) throws IOException { System.out.println("============序列化==========="); Monitoring.begin(); List<Corp> list = new ArrayList<Corp>(); for (int i = 0; i < 100000; i++) { list.add(fullObject(Corp.class)); } Monitoring.end("序列化生成数据"); // 排除首次初始化差异 JacksonMapper.toJson(list.get(0)); Monitoring.begin(); jacksonSerialize(list); Monitoring.end("序列化Jackson"); // 排除首次初始化差异 JSON.toJSONString(list.get(0)); Monitoring.begin(); fastjsonSerialize(list); Monitoring.end("序列化fastjson"); System.out.println("===========反序列化==========="); List<String> jsonStrList = new ArrayList<String>(); for (Corp corp : list) { String str = JacksonMapper.toJson(corp); jsonStrList.add(str); } Monitoring.end("反序列化生成数据"); // 排除首次初始化差异 JacksonMapper.toObj(jsonStrList.get(0), Corp.class); Monitoring.begin(); jacksonUnSerialize(jsonStrList); Monitoring.end("反序列化Jackson"); // 排除首次初始化差异 JSON.parseObject(jsonStrList.get(0), Corp.class); Monitoring.begin(); fastjsonUnSerialize(jsonStrList); Monitoring.end("反序列化fastjson"); } // ---------------------------------序列化--------------------------------- public static void jacksonSerialize(List<Corp> list) throws JsonProcessingException { for (Corp corp : list) { String str = JacksonMapper.toJson(corp); } } public static void fastjsonSerialize(List<Corp> list) { for (Corp corp : list) { String str = JSON.toJSONString(corp); } } // ---------------------------------反序列化--------------------------------- public static void jacksonUnSerialize(List<String> list) throws IOException { for (String json : list) { Corp corp = JacksonMapper.toObj(json, Corp.class); } } public static void fastjsonUnSerialize(List<String> list) { for (String json : list) { Corp corp = JSON.parseObject(json, Corp.class); } } /** * 填充一个对象(一般用于测试) */ public static <T> T fullObject(Class<T> cl) { T t = null; try { t = cl.newInstance(); Method methods[] = cl.getMethods(); for (Method method : methods) { // 如果是set方法,进行随机数据的填充 if (method.getName().indexOf("set") == 0) { Class<?> param = method.getParameterTypes()[0]; if (param.equals(String.class)) { method.invoke(t, getRandomString(5)); } else if (param.equals(Short.class)) { method.invoke(t, (short) new Random().nextInt(5)); } else if (param.equals(Float.class)) { method.invoke(t, new Random().nextFloat()); } else if (param.equals(Double.class)) { method.invoke(t, new Random().nextDouble()); } else if (param.equals(Integer.class)) { method.invoke(t, new Random().nextInt(10)); } else if (param.equals(Long.class)) { method.invoke(t, new Random().nextLong()); } else if (param.equals(Date.class)) { method.invoke(t, new Date()); } else if (param.equals(Timestamp.class)) { method.invoke(t, new Timestamp(System.currentTimeMillis())); } else if (param.equals(java.sql.Date.class)) { method.invoke(t, new java.sql.Date(System.currentTimeMillis())); } } } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return t; } public static String getRandomString(int length) { //length表示生成字符串的长度 String base = "abcdefghijklmnopqrstuvwxyz0123456789"; //生成字符串从此序列中取 Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } }
计时器:
/** * */ package com.test; /** * 计时器 * @author guoyongxiang * Date: 2014-8-20 */ public class Monitoring { private static ThreadLocal<Long> begin = new ThreadLocal<Long>(); public static void begin() { begin.set(System.currentTimeMillis()); } public static void end(String name) { double time = (System.currentTimeMillis() - begin.get()) / 1000.0; System.out.println(name + "所用时间(秒):" + time); } }
测试对象
/** * */ package com.test; import java.sql.Timestamp; /** * 对象 * @author guoyongxiang * Date: 2014-8-20 */ public class Corp { private Long uid; private Integer corpGrade; private Integer cityId; private String name; private String EName; private String description; private String zipCode; private String tel; private String fax; private String EMail; private Integer isEmailOpen; private Integer EMailChecked; private Timestamp regDateOnGov; private String backroll; private String address; private String webStoreUrl; private Integer isNew; private Integer credit; private Integer activeDegrees; private Integer hits; private Integer isHitsRecord; private Timestamp regTimeOnZfa; private Integer corpType; private Integer corpMajorcategoryId; private Integer businessRoleId; private String keyword; private Integer developState; private String isAlert; private Integer advMemState; private Integer advStockState; private Integer allianceState; private Timestamp lastUpdateTime; private Integer corpMajorcategoryId1; private String keyword1; private Long certificatePic; private Integer isUpdateCharter; private Integer currcount; private Integer curronsale; private Integer curronhot; private Integer currniccount; private Integer currniconsale; private Integer currniconhot; private String buyProducts; private Integer isOpenShop; private Integer state; private String mainProduct; private String advBrandIds; private String feature; private Integer category; private Integer contactFlag; private String fastPassage; // 省略getter/setter }
jackson 工具类(默认设置,过多设置会降低效率而且很明显,如识别json中的单引号等)
package com.test; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** * JacksonMapper * * @author guoyongxiang */ public class JacksonMapper { private static final ObjectMapper mapper = new ObjectMapper(); private JacksonMapper() { } public static ObjectMapper getInstance() { return mapper; } /** * Object to Json String * * @param obj * @return * @throws JsonProcessingException */ public static String toJson(Object obj) throws JsonProcessingException { ObjectMapper mapper = JacksonMapper.getInstance(); //SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); //mapper.setDateFormat(df); return mapper.writeValueAsString(obj); } /** * Json to List * * @param <T> * @param json * @param clazz * @return * @throws IOException * @throws JsonMappingException * @throws JsonParseException */ public static <T> List<T> toList(String json, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = JacksonMapper.getInstance(); //mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true); //mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); List<T> list = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz)); return list; } /** * Json String to Object<br> * String json = "..."; ObjectMapper mapper = JacksonMapper.getInstance();<br> * YourBean bean = mapper.readValue(json, new YourBean().getClass()); * * @param json * @param clazz * @return * @throws IOException * @throws JsonMappingException * @throws JsonParseException */ public static <T> T toObj(String json, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException{ ObjectMapper mapper = JacksonMapper.getInstance(); //mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true); //mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); return mapper.readValue(json, clazz); } /** * JsonNode to Object * @param node * @param clazz * @return * @throws JsonParseException * @throws JsonMappingException * @throws IOException */ public static <T> T toObj(JsonNode node, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException{ ObjectMapper mapper = JacksonMapper.getInstance(); return mapper.readValue(node.toString(), clazz); } /** * Json String to JsonNode * @param json * @return * @throws JsonProcessingException * @throws IOException */ public static JsonNode toNode(String json) throws JsonProcessingException, IOException{ ObjectMapper mapper = JacksonMapper.getInstance(); return mapper.readTree(json); } /** * Object to JsonNode * @param obj * @return * @throws JsonProcessingException * @throws IOException */ public static JsonNode toNode(Object obj) throws JsonProcessingException, IOException{ String json = toJson(obj); return toNode(json); } }