Ash*_*pta 8 serialization protobuf-net
我编写了一个程序来使用XMLSerializer,BinaryFormatter和ProtoBuf序列化一个'Person'类.我认为protobuf-net应该比其他两个更快.Protobuf序列化比XMLSerialization更快,但比二进制序列化慢得多.我的理解不正确吗?请让我明白这一点.感谢您的帮助.
编辑: - 我更改了代码(下面更新)来测量仅序列化的时间,而不是创建流,仍然看到差异.能告诉我为什么吗?
以下是输出: -
人在347毫秒内使用协议缓冲区创建
人在1462毫秒内使用XML创建
人在2毫秒内使用二进制创建
代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
namespace ProtocolBuffers
{
class Program
{
static void Main(string[] args)
{
string folderPath = @"E:\Ashish\Research\VS Solutions\ProtocolBuffers\ProtocolBuffer1\bin\Debug";
string XMLSerializedFileName = Path.Combine(folderPath,"PersonXMLSerialized.xml");
string ProtocolBufferFileName = Path.Combine(folderPath,"PersonProtocalBuffer.bin");
string BinarySerializedFileName = Path.Combine(folderPath,"PersonBinary.bin");
if (File.Exists(XMLSerializedFileName))
{
File.Delete(XMLSerializedFileName);
Console.WriteLine(XMLSerializedFileName + " deleted");
}
if (File.Exists(ProtocolBufferFileName))
{
File.Delete(ProtocolBufferFileName);
Console.WriteLine(ProtocolBufferFileName + " deleted");
}
if (File.Exists(BinarySerializedFileName))
{
File.Delete(BinarySerializedFileName);
Console.WriteLine(BinarySerializedFileName + " deleted");
}
var person = new Person
{
Id = 12345,
Name = "Fred",
Address = new Address
{
Line1 = "Flat 1",
Line2 = "The Meadows"
}
};
Stopwatch watch = Stopwatch.StartNew();
using (var file = File.Create(ProtocolBufferFileName))
{
watch.Start();
Serializer.Serialize(file, person);
watch.Stop();
}
//Console.WriteLine(watch.ElapsedMilliseconds.ToString());
Console.WriteLine("Person got created using protocol buffer in " + watch.ElapsedMilliseconds.ToString() + " milliseconds ");
watch.Reset();
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(person.GetType());
using (TextWriter w = new StreamWriter(XMLSerializedFileName))
{
watch.Start();
x.Serialize(w, person);
watch.Stop();
}
//Console.WriteLine(watch.ElapsedMilliseconds.ToString());
Console.WriteLine("Person got created using XML in " + watch.ElapsedMilliseconds.ToString() + " milliseconds");
watch.Reset();
using (Stream stream = File.Open(BinarySerializedFileName, FileMode.Create))
{
BinaryFormatter bformatter = new BinaryFormatter();
//Console.WriteLine("Writing Employee Information");
watch.Start();
bformatter.Serialize(stream, person);
watch.Stop();
}
//Console.WriteLine(watch.ElapsedMilliseconds.ToString());
Console.WriteLine("Person got created using binary in " + watch.ElapsedMilliseconds.ToString() + " milliseconds");
Console.ReadLine();
}
}
[ProtoContract]
[Serializable]
public class Person
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
[ProtoMember(3)]
public Address Address { get; set; }
}
[ProtoContract]
[Serializable]
public class Address
{
[ProtoMember(1)]
public string Line1 { get; set; }
[ProtoMember(2)]
public string Line2 { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 25
我回复了你的电子邮件; 我没有意识到你也在这里贴了它.我的第一个问题是:protobuf-net的哪个版本?我问的原因是"v2" 的开发主干故意禁用自动编译,因此我可以使用单元测试来测试运行时和预编译版本.因此,如果您使用的是"v2"(仅在源代码中可用),则需要告诉它编译模型 - 否则它将运行100%反射.
在"v1"或"v2"中,您可以执行以下操作:
Serializer.PrepareSerializer<Person>();
Run Code Online (Sandbox Code Playgroud)
完成后,我得到的数字(从您的电子邮件中的代码;我没有检查上面是否是相同的样本):
10
Person got created using protocol buffer in 10 milliseconds
197
Person got created using XML in 197 milliseconds
3
Person got created using binary in 3 milliseconds
Run Code Online (Sandbox Code Playgroud)
另一个因素是重复; 3-10毫秒坦率地说没事; 你无法比较这个级别的数字.加上它重复5000次(重新使用XmlSerializer/ BinaryFormatter实例;没有引入虚假成本)我得到:
110
Person got created using protocol buffer in 110 milliseconds
329
Person got created using XML in 329 milliseconds
133
Person got created using binary in 133 milliseconds
Run Code Online (Sandbox Code Playgroud)
把它带到极端的极端(100000):
1544
Person got created using protocol buffer in 1544 milliseconds
3009
Person got created using XML in 3009 milliseconds
3087
Person got created using binary in 3087 milliseconds
Run Code Online (Sandbox Code Playgroud)
最终:
另请注意,在"v2"中,已编译的模型可以完全静态编译(到可以部署的dll),甚至可以消除(已经很小的)旋转成本.
我的意见与明确的答案略有不同.我认为这些测试中的数字反映了二进制格式化程序的元数据开销.BinaryFormatter在写入数据之前首先写入有关类的元数据,而protobuf仅写入数据.
对于测试中非常小的对象(一个Person对象),二进制格式化程序的元数据成本比实际情况更重,因为它编写的元数据多于数据.因此,当您增加重复次数时,元数据成本会被夸大,在极端情况下会达到与xml序列化相同的水平.
如果序列化Person数组,并且数组足够大,则元数据成本对总成本来说是微不足道的.然后二进制格式化程序应该执行类似于protobuf的极端重复测试.
PS:我找到了这个页面,因为我正在评估不同的序列化器.我还找到了一个博客http://blogs.msdn.com/b/youssefm/archive/2009/07/10/comparing-the-performance-of-net-serializers.aspx,它显示了DataContractSerializer +二进制XmlDictionaryWriter执行的测试结果比二进制格式化器好几倍.它还测试了非常小的数据.当我使用大量数据进行测试时,我惊讶地发现结果非常不同.因此,请使用您实际使用的实际数据进行测试.
| 归档时间: |
|
| 查看次数: |
10129 次 |
| 最近记录: |