.net 各种序列化方式效率对比
在服务与服务之间传输的是二进制数据,而在此之前有多种方法将数据内容进行序列化来减小数据传递大小,现针对于目前主流的几种序列化方式做了简单数据统计对比。
先做下简单介绍↓↓↓
1、protobuf-net
protobuf-net is a contract based serializer for .NET code, that happens to write data in the "protocol buffers" serialization format engineered by Google. The API, however, is very different to Google's, and follows typical .NET patterns (it is broadly comparable, in usage, to XmlSerializer, DataContractSerializer, etc). It should work for most .NET languages that write standard types and can use attributes.
GitHub地址:https://github.com/mgravell/protobuf-net
2、Newtonsoft.Json(Json.Net)
Json.NET is a personal open source project. Started in 2006, thousands of hours have been invested in refining and tuning Json.NET with the goal of making it not just the best JSON serializer for .NET but the best serializer for any computer language.
官网:https://www.newtonsoft.com/json
3、DataContractSerializer
Use the DataContractSerializer class to serialize and deserialize instances of a type into an XML stream or document. For example, you can create a type named Person with properties that contain essential data, such as a name and address. You can then create and manipulate an instance of the Person class and write all of its property values in an XML document for later retrieval, or in an XML stream for immediate transport. Most important, the DataContractSerializer is used to serialize and deserialize data sent in Windows Communication Foundation (WCF) messages. Apply the DataContractAttribute attribute to classes, and the DataMemberAttribute attribute to class members to specify properties and fields that are serialized.
现对于这三种序列化方式从序列化后数据大小、序列化耗时、反序列化耗时进行统计对比。
版本:protobuf-net-2.3.2.0、Newtonsoft.Json-6.0.4
统计代码:
class Program
{
static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("****************第一次测试****************");
Console.WriteLine();
TestMain();
Console.WriteLine();
Console.WriteLine("****************第二次测试****************");
Console.WriteLine();
TestMain();
Console.WriteLine();
Console.WriteLine("****************第三次测试****************");
Console.WriteLine();
TestMain();
Console.Read();
} #region Private private static void TestMain(int count)
{
var list = GetList(count); var pbSerializeTime = 0.00;
var pbDeSerializeTime = 0.00; var jsonSerializeTime = 0.00;
var jsonDeSerializeTime = 0.00; var dataContractSerializeTime = 0.00;
var dataContractDeSerializeTime = 0.00; Console.WriteLine(); //protobuf-net
Console.WriteLine("---------------protobuf-net--------------");
Stopwatch watch = new Stopwatch();
watch.Start();
var pbResult = ProtobufSerialize(list);
File.WriteAllText($@"D:\Code\WCF数据压缩传输\WcfTest{DateTime.Now.ToString("yyyyMMddHHmmss")}.txt", pbResult);
watch.Stop(); pbSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine();
Console.WriteLine($"序列化后数据大小:{HumanReadableFilesize(pbResult.Length)}");
Console.WriteLine();
Console.WriteLine($"序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine(); watch = new Stopwatch();
watch.Start();
var pbValue = ProtobufDeSerialize<List<TransmissionModel>>(pbResult);
watch.Stop();
pbDeSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine($"反序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine(); Console.WriteLine($"反序列化结果验证:{pbValue[0].Name}:{!string.IsNullOrWhiteSpace(pbValue[0].Name)}");
Console.WriteLine(); //Newtonsoft.Json
Console.WriteLine("---------------Newtonsoft.Json--------------");
Console.WriteLine();
watch = new Stopwatch();
watch.Start();
var jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(list);
File.WriteAllText($@"D:\Code\WCF数据压缩传输\WcfTest{DateTime.Now.AddSeconds(1).ToString("yyyyMMddHHmmss")}.txt", jsonResult);
watch.Stop();
jsonSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine($"序列化后数据大小:{HumanReadableFilesize(jsonResult.Length)}");
Console.WriteLine();
Console.WriteLine($"序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine(); watch = new Stopwatch();
watch.Start();
var jsonValue = Newtonsoft.Json.JsonConvert.DeserializeObject<List<TransmissionModel>>(jsonResult);
watch.Stop();
jsonDeSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine($"反序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine(); Console.WriteLine($"反序列化结果验证:{jsonValue[0].Name}:{!string.IsNullOrWhiteSpace(jsonValue[0].Name)}");
Console.WriteLine(); //DataContractSerializer
Console.WriteLine("---------------DataContractSerializer--------------");
Console.WriteLine(); watch = new Stopwatch();
watch.Start();
var dataContractFileName = $@"D:\Code\WCF数据压缩传输\WcfTest{DateTime.Now.AddSeconds(2).ToString("yyyyMMddHHmmss")}.txt";
var dataContractSerializer = new DataContractSerializer(typeof(List<TransmissionModel>));
var dataContractfi = new FileInfo(dataContractFileName);
using (var stream = dataContractfi.Create())
{
dataContractSerializer.WriteObject(stream, list);
}
watch.Stop();
dataContractSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine($"序列化后数据大小:{HumanReadableFilesize(dataContractfi.Length)}");
Console.WriteLine();
Console.WriteLine($"序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine(); watch = new Stopwatch();
watch.Start();
var dataContractValue = new List<TransmissionModel>();
DataContractSerializer serializer = new DataContractSerializer(typeof(List<TransmissionModel>));
using (FileStream fs = new FileStream(dataContractFileName, FileMode.Open, FileAccess.Read))
{
using (XmlReader reader = new XmlTextReader(dataContractFileName, fs))
{
dataContractValue = (List<TransmissionModel>)serializer.ReadObject(reader);
}
}
watch.Stop();
dataContractDeSerializeTime = watch.ElapsedMilliseconds;
Console.WriteLine($"反序列化耗时:{watch.ElapsedMilliseconds} 毫秒");
Console.WriteLine();
Console.WriteLine($"反序列化结果验证:{dataContractValue[0].Name}:{!string.IsNullOrWhiteSpace(dataContractValue[0].Name)}"); //统计结果
Console.WriteLine();
Console.WriteLine($"=====================统计结果======================");
Console.WriteLine();
Console.WriteLine($"protobuf-net序列化后数据大小为Newtonsoft.Json的 {Math.Round(pbResult.Length / Convert.ToDouble(jsonResult.Length), 2) * 100}%,为DataContractSerializer的 {Math.Round(pbResult.Length / Convert.ToDouble(dataContractfi.Length), 2) * 100}%");
Console.WriteLine();
Console.WriteLine($"protobuf-net序列化耗时为Newtonsoft.Json的 {Math.Round(pbSerializeTime / jsonSerializeTime, 2) * 100}%,为DataContractSerializer的 {Math.Round(pbSerializeTime / dataContractSerializeTime, 2) * 100}%");
Console.WriteLine();
Console.WriteLine($"protobuf-net反序列耗时为Newtonsoft.Json的 {Math.Round(pbDeSerializeTime / jsonDeSerializeTime, 2) * 100}%,为DataContractSerializer的 {Math.Round(pbDeSerializeTime / dataContractDeSerializeTime, 2) * 100}%");
Console.WriteLine();
} private static List<TransmissionModel> GetList(int count)
{
var list = new List<TransmissionModel>();
var model1 = new TransmissionModel() { ID = , Name = "我爱北京天安门", TempModel = new TempModel() { Age = , Name = "天安门上有毛爷爷" } };
var model2 = new TransmissionModel() { ID = , Name = "天安门上红旗飘", TempModel = new TempModel() { Age = , Name = "I Love 毛爷爷" } };
for (int i = ; i < count; i++)
{
list.Add(model1);
list.Add(model2);
}
return list;
} private static string ProtobufSerialize<T>(T obj)
{
using (var memory = new MemoryStream())
{
Serializer.Serialize(memory, obj);
return Encoding.UTF8.GetString(memory.ToArray());
}
} /// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="content"></param>
/// <returns></returns>
private static T ProtobufDeSerialize<T>(string content)
{
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
T t = Serializer.Deserialize<T>(ms);
return t;
}
} /// <summary>
/// 转换方法
/// </summary>
/// <param name="size">字节值</param>
/// <returns></returns>
private static String HumanReadableFilesize(double size)
{
String[] units = new String[] { "B", "KB", "MB", "GB", "TB", "PB" };
double mod = 1024.0;
int i = ;
while (size >= mod)
{
size /= mod;
i++;
}
return Math.Round(size) + units[i];
}
#endregion
} [DataContract]
[ProtoContract]
class TransmissionModel
{
[DataMember]
[ProtoMember()]
public int ID { get; set; } [DataMember]
[ProtoMember()]
public string Name { get; set; } [DataMember]
[ProtoMember()]
public TempModel TempModel { get; set; }
} [DataContract]
[ProtoContract]
class TempModel
{
[DataMember]
[ProtoMember()]
public int Age { get; set; } [DataMember]
[ProtoMember()]
public string Name { get; set; }
}
测试统计结果如下:
****************第一次测试**************** ---------------protobuf-net-------------- 序列化后数据大小:27KB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------Newtonsoft.Json-------------- 序列化后数据大小:65KB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------DataContractSerializer-------------- 序列化后数据大小:148KB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True =====================统计结果====================== protobuf-net序列化后数据大小为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net序列化耗时为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net反序列耗时为Newtonsoft.Json的 %,为DataContractSerializer的 % ****************第二次测试**************** ---------------protobuf-net-------------- 序列化后数据大小:273KB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------Newtonsoft.Json-------------- 序列化后数据大小:654KB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------DataContractSerializer-------------- 序列化后数据大小:1MB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True =====================统计结果====================== protobuf-net序列化后数据大小为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net序列化耗时为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net反序列耗时为Newtonsoft.Json的 %,为DataContractSerializer的 % ****************第三次测试**************** ---------------protobuf-net-------------- 序列化后数据大小:3MB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------Newtonsoft.Json-------------- 序列化后数据大小:6MB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True ---------------DataContractSerializer-------------- 序列化后数据大小:14MB 序列化耗时: 毫秒 反序列化耗时: 毫秒 反序列化结果验证:我爱北京天安门:True =====================统计结果====================== protobuf-net序列化后数据大小为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net序列化耗时为Newtonsoft.Json的 %,为DataContractSerializer的 % protobuf-net反序列耗时为Newtonsoft.Json的 %,为DataContractSerializer的 %
各序列化生成文件内容对比:
protobuf-net:
Newtonsoft.Json:
DataContractSerializer:
综合分析:
1、数据内容格式及大小:DataContractSerializer(序列化为XML)> Newtonsoft.Json(序列化为Json文本) > protobuf-net(暂未知格式) ,protobuf-net 表现最优,protobuf-net序列化后数据大小为Newtonsoft.Json的 42%,为DataContractSerializer的 19%。
2、序列化耗时最小方面:随着数据本身大小的变化各序列化耗时之间的排名有不同变化,表现较好的主要为 DataContractSerializer 和 protobuf-net ,三轮测试下来 Newtonsoft.Json 明显比其它两种序列化方式耗时长(详细查看上方测试统计数据)。
3、反序列耗时最小方面:随着数据本身大小的变化排名也有不同变化,表现最好的为protobuf-net(详细查看上方测试统计数据)。
客观结论:
通过对比序列化后数据大小、序列化耗时、反序列化耗时、数据格式得出客观结论:protobuf-net 在整体效率上来说最优。
关于 protobuf-net 的具体应用将会在下篇文章写出。
以上仅为个人测试统计对比,欢迎提出建议指正。
本文参考文章:http://www.cnblogs.com/onlytiancai/archive/2009/07/02/protobuf_net_test.html
↓↓↓欢迎关注我的公众号
.net 各种序列化方式效率对比的更多相关文章
- Golang 序列化方式及对比
Golang 序列化方式及对比 - fengfengdiandia的专栏 - CSDN博客 https://blog.csdn.net/fengfengdiandia/article/details/ ...
- Lua大量字符串拼接方式效率对比及原因分析
Lua大量字符串拼接方式效率对比及原因分析_AaronChan的博客-CSDN博客_lua字符串拼接消耗 https://blog.csdn.net/qq_26958473/article/detai ...
- PYTHON解析XML的多种方式效率对比实测
在最初学习PYTHON的时候,只知道有DOM和SAX两种解析方法,但是其效率都不够理想,由于需要处理的文件数量太大,这两种方式耗时太高无法接受. 在网络搜索后发现,目前应用比较广泛,且效率相对较高的E ...
- 判断字符串中是否存在的几种方案:string.indexof、string.contains、list.contains、list.any几种方式效率对比
我们在做项目时,可能会遇到这样的需求,比如判断,1,2,3,33,22,123, 中是否存在,3,. var str=",1,2,3,33,22,123,"; 一般有几种方式: 1 ...
- Spark入Hbase的四种方式效率对比
一.方式介绍 本次测试一种采用了四种方式进行了对比,分别是:1.在RDD内部调用java API.2.调用saveAsNewAPIHadoopDataset()接口.3.saveAsHadoopDat ...
- SqlServer的两种插入方式效率对比
protected void button1_Click(object sender, EventArgs e) { DataTable dtSource = new DataTable(); dtS ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- springboot系列十一、redisTemplate和stringRedisTemplate对比、redisTemplate几种序列化方式比较
一.redisTemplate和stringRedisTemplate对比 RedisTemplate看这个类的名字后缀是Template,如果了解过Spring如何连接关系型数据库的,大概不会难猜出 ...
- java中多种写文件方式的效率对比实验
一.实验背景 最近在考虑一个问题:“如果快速地向文件中写入数据”,java提供了多种文件写入的方式,效率上各有异同,基本上可以分为如下三大类:字节流输出.字符流输出.内存文件映射输出.前两种又可以分为 ...
随机推荐
- 【Oracle】控制文件管理
/* 控制文件是oracle数据库最重要的物理文件之一,每个oracle数据库都必须有一个控制文件,在启动数据库实例时, oracle会根据初始化参数查找到控制文件的名称及位置信息,并读取控制文件的内 ...
- Python3 TA-Lib
This is a Python wrapper for TA-LIB based on Cython instead of SWIG. From the homepage: TA-Lib is wi ...
- 简单sql注入学习
sql注入是什么? 所谓SQL注入,就是通过把SQL命令插入到Web表单提 交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQ ...
- 读书笔记--C陷阱与缺陷(二)
第二章 1. 理解函数声明 书中分析了复杂的类型声明方式,也说明了使用typedef声明会更好理解,推荐大家使用typedef进行函数声明. 书中类型分析一层一层挖掘,让读者可以理解多层嵌套的类型含义 ...
- SQL分组查询
把数据分成多个逻辑组,以便能对每个组的数据进行操作,对每个组进行聚集计算. 1.创建分组 分组是在SELECT语句的GROUP BY子句中建立的 例子: SELECT vendId ...
- [2014-08-18]初尝 AspNet vNext On Mac
网上关于AspNet vNext的介绍已经非常多,本文不再赘述,仅记录下Mac环境的几点注意事项. 环境 OSX 10.9.4 Mono 3.6.1 Kvm 1.0.0-alpha4-10285 mo ...
- MySQL(二)之服务管理与初始化文件修改和连接MySQL
上一篇给大家介绍了怎么在linux和windows中安装mysql,本来是可以放在首页的,但是博客园说“安装配置类文件”不让放在首页.接下来给大家介绍一下在linux和windows下MySQL的一下 ...
- H5性能测试学习
工欲善其事,必先利其器,在做H5前端性能测试之前,选择合适的工具能让我们的测试工作事半功倍.本文要提到的工具有两类: 一类是抓包工具,如Fiddler.Charles等.这类工具不仅可以抓包,还可以对 ...
- [js高手之路]javascript腾讯面试题学习封装一个简易的异步队列
这道js的面试题,是这样的,页面上有一个按钮,一个ul,点击按钮的时候,每隔1秒钟向ul的后面追加一个li, 一共追加10个,li的内容从0开始技术( 0, 1, 2, ....9 ),首先我们用闭包 ...
- ORACLE SEQUENCE的简单介绍
先假设有这么一个表: create table S_Depart ( DepartId INT not null, DepartName NVARCHAR2() not null, DepartOrd ...