【发布时间】:2010-06-03 13:42:33
【问题描述】:
我编写了一个程序来使用 XMLSerializer、BinaryFormatter 和 ProtoBuf 序列化一个“Person”类。我认为 protobuf-net 应该比其他两个更快。 Protobuf 序列化比 XMLSerialization 快,但比二进制序列化慢得多。我的理解不正确吗?请让我明白这一点。谢谢你的帮助。
编辑:- 我更改了代码(在下面更新)以测量仅用于序列化而不是创建流的时间,并且仍然看到差异。谁能告诉我为什么?
以下是输出:-
在 347 毫秒内使用协议缓冲区创建人员
使用 XML 在 1462 毫秒内创建人
在 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; }
}
}
【问题讨论】:
-
一些快速注意事项 - 首先,尽量减少外部因素对您的测试的影响。序列化到内存流或其他一些相对性能中立的目标,而不是文件系统。其次,您应该只为序列化操作计时 - 不要包括创建流或构建对象。第三,重复测试合理次数并报告汇总结果。
-
感谢 cmets。您提到了“相对性能中立的目标而不是文件系统”。这意味着什么?您能否举一些“相对绩效目标”的例子?谢谢。
-
@Ashish - 我主要考虑的是内存流。如果您序列化到内存流,环境可能仍然会影响您的测试(例如,内存压力可能会迫使您进入虚拟内存进行一项测试而不是另一项测试),但我认为它会与文件系统相比,不太可能影响您的结果。回想起来,重复测试可能比尝试获得绝对中立的测试条件更重要,但努力争取这些条件不会受到伤害。 ;)
-
@Jeff Sternal - 或者至少可以在 using 语句中移动秒表。那么文件的创建或文件的关闭就没有延迟了。
-
@Jeff Sternal - 感谢您抽出宝贵时间。实时,我肯定需要创建相当多的文件,我不能将它们保存到内存流中。您认为汇总(创建大量文件)时间比较会有所不同吗?
标签: serialization protobuf-net