【发布时间】:2011-04-26 08:34:22
【问题描述】:
我测试了 protobuf 序列化,似乎对于低于一定数量的对象,它比常规的 datacontract 序列化慢。使用 DataContractSerializer 传输大小更大,但在序列化和反序列化过程中使用 DataContractSerializer 更快
你认为这是正常的还是我弄错了?
[DataContract]
public partial class Toto
{
[DataMember]
public string NomToto { get; set; }
[DataMember]
public string PrenomToto { get; set; }
}
这是我的数据合同类,这与 protobuf 相同
[ProtoContract]
public partial class Titi
{
[ProtoMember(1)]
public string NomTiti { get; set; }
[ProtoMember(2)]
public string PrenomTiti { get; set; }
}
这是我使用 protobuf 进行 WCF 服务的方法(对于没有 ms 的数据合同也是如此)
public class TitiService : ITitiService
{
public byte[] GetAllTitis()
{
List<Titi> titiList = new List<Titi>();
for (int i = 0; i < 20000; i++)
{
var titi = new Titi
{
NomTiti = "NomTiti" + i,
PrenomTiti = "PrenomTiti" + i
};
titiList.Add(titi);
}
var ms = new MemoryStream();
Serializer.Serialize(ms, titiList);
byte[] arr = ms.ToArray();
return arr;
}
}
带有数据契约的服务
public class TotoService : ITotoService
{
public List<Toto> GetAllTotos()
{
List<Toto> totoList = new List<Toto>();
for (int i = 0; i<20000; i++)
{
var toto = new Toto
{
NomToto = "NomToto" + i,
PrenomToto = "PrenomToto" + i
};
totoList.Add(toto);
}
return totoList;
}
}
这里是客户端调用
public partial class Program
{
static ProtobufTestAzure.Client.TitiService.TitiServiceClient TitiClient;
static ProtobufTestAzure.Client.TotoService.TotoServiceClient TotoClient;
public static void Main(string[] args)
{
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
Stopwatch stopwatch3 = new Stopwatch();
stopwatch1.Start();
TitiClient = new ProtobufTestAzure.Client.TitiService.TitiServiceClient();
Byte[] titiByte = TitiClient.GetAllTitis();
TitiClient.Close();
stopwatch1.Stop();
stopwatch2.Start();
var ms = new MemoryStream(titiByte);
List<Titi> TitiList = Serializer.Deserialize<List<Titi>>(ms);
stopwatch2.Stop();
Console.WriteLine(" ");
stopwatch3.Start();
TotoClient = new ProtobufTestAzure.Client.TotoService.TotoServiceClient();
var TotoList = TotoClient.GetAllTotos();
TotoClient.Close();
stopwatch3.Stop();
Console.WriteLine("Time elapse for reception (Protobuf): {0} ms ({1} éléments)", stopwatch1.ElapsedMilliseconds, TitiList.Count);
Console.WriteLine("Time elapse for deserialization (Protobuf : {0} ms ({1} éléments)", stopwatch2.ElapsedMilliseconds, TitiList.Count);
Console.WriteLine("Time elapse for réception (Datacontract Serialization) : {0} ms ({1} éléments)", stopwatch3.ElapsedMilliseconds, TotoList.Count);
Console.ReadLine();
}
}
以及 10000 个对象的结果
接收时间 (Protobuf):3359 毫秒(10000 个元素) 反序列化所用时间 (Protobuf):138 毫秒(10000 个元素) 接收时间流逝(Datacontract序列化):2200ms(10000个元素)
我用 20000 个对象对其进行了测试 它给了我第一个电话
接收时间(Protobuf):11258ms(20000 个元素) 反序列化所用时间(Protobuf):133ms(20000 个元素) 接收时间(Datacontract序列化):3726ms(20000个元素)
第二次通话
接收时间 (Protobuf):2844 毫秒(20000 个元素) 反序列化所用时间 (Protobuf):141 毫秒(20000 个元素) 接收时间流逝(Datacontract 序列化):7541 毫秒(20000 个元素)
第三个
接收时间(Protobuf):2767ms(20000 个元素) 反序列化所用时间 (Protobuf):145 毫秒(20000 个元素) 接收时间流逝(Datacontract 序列化):3989 毫秒(20000 个元素)
在“Protobuf transfert”上激活 MTOM 后,它给了我:
第一次通话
接收时间 (Protobuf):3316 毫秒(20000 个元素) 反序列化所用时间(Protobuf):63 ms(20000 个元素) 接收时间流逝(Datacontract 序列化):3769 毫秒(20000 个元素)
第二次通话
接收时间 (Protobuf):2279 毫秒(20000 个元素) 反序列化所用时间(Protobuf):57 毫秒(20000 个元素) 接收时间流逝(Datacontract 序列化):3959 毫秒(20000 个元素)
我为对象大小添加了这部分代码
long totoSize = new long();
using (Stream s = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(s, totoList);
totoSize = s.Length;
}
long titiSize = titiByte.Count();
它给了我 637780 和 protobuf 和 1038236 和 DataContractSerializer 今天早上的通话时间更好,更稳定 第一次通话 protobuf = 2498 毫秒 数据合约 = 5085 毫秒
第二次通话 protobuf = 3649 毫秒 数据合约 = 3840 毫秒
第三次调用 protobuf = 2498 毫秒 数据合约 = 5085 毫秒
【问题讨论】:
-
你怎么能指望有人告诉你如果你犯了一个错误而不显示你实际做了什么,例如显示你测试过的代码(它的两个版本)?
-
能否发布您的方法和代码(如果存在)进行测试?
-
顺便说一句,常规 XML 序列化!= datacontract 序列化;两者是相关的,但非常不同。但我赞同上述观点;没有更多的上下文,这是不可能评论的。
-
对不起,XML序列化和Datacontract序列化的错误,我使用最后一个,我用我的代码编辑
-
@Marc 我用 WireShark 对其进行了测试,它给了我大约 700 Ko 的 protobuf 和 2Mo 的 dataContractSerializer,你做得真好
标签: c# datacontractserializer protobuf-net