我正在使用Protobuf-net实现一个wcf请求/响应服务,用于序列化和tcp绑定。在运行同一台机器上运行的服务器和客户端的测试中,我看到,对于大约1.5Mb的响应对象,一个大约500ms的空转时间。
当我将同一个对象序列化为内存流时,在接收到客户端上的响应后,大约需要115毫秒,并且大约需要330.ms左右。 考虑到从数据库等查询数据的开销,这种总计往返时间加起来
我已经看到它写的这可能是消息大小限制,应该使用原型缓冲区,但这是我可以期待的那种序列化/解除时间吗? protobuf-net是否有任何尺寸/速度权衡选项? 感谢
这是目前的模型......
public class BaseResponse
{
public bool Success {get;set;}
public string Error {get;set;}
}
public class SourceTableResponse : BaseResponse
{
public Dictionary<string, Dictionary<string,string>> FieldValuesByTableName {get;set;}
}
答案 0 :(得分:4)
有一些技巧可以帮到这里,是的。其中最常见的是尽可能使用“分组”数据。解释一下:“群组”是protobuf规范的一个特征,谷歌不会使用太多 - 他们建议默认为子对象的长度前缀表示法 - 但长度前缀写入相对昂贵。在大多数情况下,这就像在一些注释中添加DataFormat = DataFormat.Group
一样简单,但是:当您拥有Dictionary<string,Dictionary<string,string>>
时,这并不是那么简单 - 因为KeyValuePair<,>
是 protocuf-net保护,以防止好心的用户破坏它:它不会让你改变格式。我们仍然可以做这个,但是:我们需要编写自己的模型而不是使用裸字典 - 有点痛苦。
其他技巧:
Dictionary<string,string>
,尽管但从根本上讲:您的数据目前将由UTF-8 支配 - 无论是在存储和处理方面。我不能做太多,因为你把所有东西都存储为字符串。就个人而言,我会说这个非常宽松的模型并不适合充分利用protobuf-net;我所能做的就是在极限范围内尽可能地收紧它。例如,这仅适用于前向(无缓冲):
[ProtoContract]
[ProtoInclude(3, typeof(CustomSourceTableResponse), DataFormat = DataFormat.Group)]
public class CustomBaseResponse
{
[ProtoMember(1)]
public bool Success { get; set; }
[ProtoMember(2)]
public string Error { get; set; }
}
[ProtoContract]
public class CustomSourceTableResponse : CustomBaseResponse
{
[ProtoMember(1, DataFormat = DataFormat.Group)]
public List<FieldTable> FieldValuesByTableName { get { return fieldValuesByTableName; } }
private readonly List<FieldTable> fieldValuesByTableName = new List<FieldTable>();
}
[ProtoContract]
public class FieldTable
{
public FieldTable() { }
public FieldTable(string tableName)
{
TableName = tableName;
}
[ProtoMember(1)]
public string TableName { get; set; }
[ProtoMember(2, DataFormat = DataFormat.Group)]
public List<FieldValue> FieldValues { get { return fieldValues; } }
private readonly List<FieldValue> fieldValues = new List<FieldValue>();
}
[ProtoContract]
public class FieldValue
{
public FieldValue() { }
public FieldValue(string name, string value)
{
Name = name;
Value = value;
}
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public string Value { get; set; }
}
如果你期望有很多重复的FieldValue.Name
值(例如,有很多行,每行都有相同的字段),那么......好吧,坦率地说我建议使用适当的基于类型的模型,即
class SomeRow {
public int Id {get;set;}
public string Name {get;set;}
public DateTime DateOfBirth {get;set;}
}
但是如果那是不可能的,那么我想你仍然可以避免在数据中使用"DateOfBirth"
200次:
[ProtoMember(1, AsReference=true)]
public string Name { get; set; }
[ProtoMember(2)]
public string Value { get; set; }
但请注意:由于多种原因,真的非常比使用打字模型贵得多: