问题描述
我编写了一个程序来使用 XMLSerializer、BinaryFormatter 和 ProtoBuf 序列化Person"类.我认为 protobuf-net 应该比其他两个更快.Protobuf 序列化比 XMLSerialization 快,但比二进制序列化慢得多.我的理解不正确吗?请让我明白这一点.谢谢你的帮助.
I wrote a program to serialize a 'Person' class using XMLSerializer, BinaryFormatter and ProtoBuf. I thought protobuf-net should be faster than the other two. Protobuf serialization was faster than XMLSerialization but much slower than the binary serialization. Is my understanding incorrect? Please make me understand this. Thank you for the help.
- 我更改了代码(在下面更新)以仅测量序列化的时间而不是创建流,但仍然可以看到差异.谁能告诉我为什么?
以下是输出:-
Person 在 347 毫秒内使用协议缓冲区创建
Person got created using protocol buffer in 347 milliseconds
使用 XML 在 1462 毫秒内创建一个人
Person got created using XML in 1462 milliseconds
在 2 毫秒内使用二进制创建了一个人
Person got created using binary in 2 milliseconds
下面的代码
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; }
}
}
推荐答案
我回复了你的邮件;没想到你也发到这里了.我的第一个问题是:protobuf-net 是哪个版本?我问的原因是v2"的开发主干故意禁用了自动编译,以便我可以使用我的单元测试来测试运行时和预编译版本.因此,如果您使用v2"(仅在源代码中可用),您需要告诉它编译模型 - 否则它会运行 100% 反射.
I replied to your e-mail; I didn't realise you'd also posted it here. The first question I have is: which version of protobuf-net? The reason I ask is that the development trunk of "v2" deliberately has auto-compilation disabled, so that I can use my unit tests to test both the runtime and pre-compiled versions. So if you are using "v2" (only available in source), you need to tell it to compile the model - otherwise it is running 100% reflection.
在v1"或v2"中,您可以使用:
In either "v1" or "v2" you can do this with:
Serializer.PrepareSerializer<Person>();
完成此操作后,我得到的数字(来自您电子邮件中的代码;我没有检查以上是否为同一个样本):
Having done this, the numbers I get (from the code in your e-mail; I haven't checked if the above is the same sample):
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
另一个因素是重复;坦率地说,3-10ms 不算什么;你无法比较这个级别的数字.将其重复 5000 次(重新使用 XmlSerializer
/BinaryFormatter
实例;没有引入虚假成本)我得到:
The other factor is the repeats; 3-10ms is frankly nothing; you can't compare numbers around this level. Upping it to repeat 5000 times (re-using the XmlSerializer
/ BinaryFormatter
instances; no false costs introduced) I get:
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
将其推向更愚蠢的极端(100000):
Taking this to sillier extremes (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
最终:
- 当您几乎没有要序列化的数据时,大多数方法都会非常快(包括 protobuf-net)
- 随着您添加数据,差异变得更加明显;protobuf 通常在这方面表现出色,无论是单个大图,还是大量小图
另请注意,在v2"中,编译模型可以完全静态编译(到您可以部署的 dll),甚至消除(已经很小)启动成本.
Note also that in "v2" the compiled model can be fully static-compiled (to a dll that you can deploy), removing even the (already small) spin-up costs.
这篇关于protobuf-net 不比二进制序列化快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!