protobuf-net与DataContractSerializer在WCF上的性能比较
本文关键字:性能 性能比 比较 WCF DataContractSerializer protobuf-net | 更新日期: 2023-09-27 17:52:52
我测试了protobuf序列化,似乎对于低于一定数量的对象,它比常规的数据契约序列化要慢。使用DataContractSerializer传输大小更大,但在序列化和反序列化期间,使用DataContractSerializer速度更快
你认为这是正常的还是我犯了一个错误?
[DataContract]
public partial class Toto
{
[DataMember]
public string NomToto { get; set; }
[DataMember]
public string PrenomToto { get; set; }
}
这是我的datacontract类对于protobuf也是一样的
[ProtoContract]
public partial class Titi
{
[ProtoMember(1)]
public string NomTiti { get; set; }
[ProtoMember(2)]
public string PrenomTiti { get; set; }
}
这是我的方法WCF服务与protobuf(相同的数据合约没有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 ms(10000个元素)反序列化时间(Protobuf): 138 ms(10000个元素)接收时间(数据合约序列化):2200ms(10000个元素)
我用20000个对象测试它它给了我第一个电话
接收时间(Protobuf): 11258ms(20000个元素)反序列化时间(Protobuf): 133ms(20000个元素)接收时间(数据合约序列化):3726ms(20000个元素)
第二个呼叫
接收时间(Protobuf): 2844 ms(20000个元素)反序列化时间(Protobuf): 141 ms(20000个元素)接收时间(数据合约序列化):7541毫秒(20000个元素)
为第三个
接收时间(Protobuf): 2767ms(20000个元素)反序列化时间(Protobuf): 145 ms(20000个元素)接收时间(数据合约序列化):3989毫秒(20000个元素)
在MTOM激活'Protobuf transfer '后,它给了我:
第一次调用
接收时间(Protobuf): 3316 ms(20000个元素)反序列化时间(Protobuf): 63 ms(20000个元素)接收时间(数据合约序列化):3769毫秒(20000个元素)
第二次呼叫
接收时间(Protobuf): 2279 ms(20000个元素)反序列化时间(Protobuf): 57 ms(20000个元素)接收时间(数据合约序列化):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 ms数据合约= 5085毫秒
第二个电话Protobuf = 3649 ms数据合约= 3840毫秒
第三个电话Protobuf = 2498 ms数据合约= 5085 ms
影响性能的一些因素:
- 序列化器准备好了吗?在第一次使用每个类型时,这是自动的;第一次通过,它需要做相当多的检查等,以弄清楚你的模型是如何工作的。您可以通过在启动期间某处调用
Serializer.PrepareSerializer<YourType>()
来抵消这一点- 或者作为替代方案,在v2中(作为"alpha"可用),如果您需要尽可能快的冷启动性能,您可以将序列化器预生成为dll
- 什么是运输?特别是WCF,你需要记住你的
byte[]
是如何编码的(这不是套接字的问题,当然);例如,运输可以使用MTOM吗?或者是64进制编码的byte[]
?- ,并注意
Stream
和byte[]
可能被不同地处理;如果你可以测量带宽,你可能想要尝试 如果绝对速度是您的目标,那么启用MTOM的 - basic-http是我对WCF传输的首选;或套接字,如果你想接近限制
- ,并注意