Serialization protobuf net是否有用于序列化的内置压缩?

Serialization protobuf net是否有用于序列化的内置压缩?,serialization,protobuf-net,binary-serialization,Serialization,Protobuf Net,Binary Serialization,我在对BinaryFormatter和protobuf net serializer进行比较,我对自己的想法很满意,但奇怪的是protobuf net成功地将对象序列化为一个更小的字节数组,而不是将每个属性的值写入一个没有任何元数据的字节数组 我知道如果您将AsReference设置为true,protobuf-net支持字符串插入,但在这种情况下我不会这样做,那么protobuf-net默认提供一些压缩吗 以下是一些代码,您可以自己运行查看: var simpleObject=新的simple

我在对BinaryFormatter和protobuf net serializer进行比较,我对自己的想法很满意,但奇怪的是protobuf net成功地将对象序列化为一个更小的字节数组,而不是将每个属性的值写入一个没有任何元数据的字节数组

我知道如果您将
AsReference
设置为
true
,protobuf-net支持字符串插入,但在这种情况下我不会这样做,那么protobuf-net默认提供一些压缩吗

以下是一些代码,您可以自己运行查看:

var simpleObject=新的simpleObject
{
Id=10,
Name=“Yan”,
地址=“地球”,
分数=可枚举范围(1,10).ToList()
};
使用(var memStream=new MemoryStream())
{
var binaryWriter=新的binaryWriter(memStream);
//整数为4字节
binaryWriter.Write(simpleObject.Id);
//3个字节+1个字节用于字符串终止
binaryWriter.Write(simpleObject.Name);
//12个字节+1个字节用于字符串终止
binaryWriter.Write(simpleObject.Address);
//40字节代表10整数
simpleObject.Scores.ForEach(binaryWriter.Write);
//61字节,这是我所期望的
WriteLine(“BinaryWriter写入[{0}]字节”,
memStream.ToArray().Count());
}
使用(var memStream=new MemoryStream())
{
ProtoBuf.Serializer.Serialize(memStream,simpleObject);
//41字节!
WriteLine(“Protobuf序列化写入[{0}]字节”,
memStream.ToArray().Count());
}
编辑:忘记添加,
SimpleObject
类如下所示:

[可序列化]
[数据合同]
公共类SimpleObject
{
[数据成员(顺序=1)]
公共int Id{get;set;}
[数据成员(顺序=2)]
公共字符串名称{get;set;}
[数据成员(顺序=3)]
公共字符串地址{get;set;}
[数据成员(顺序=4)]
公共列表分数{get;set;}
}

不,它没有;protobuf规范中没有规定“压缩”;但是,它(默认情况下)使用“可变长度编码”——整数数据的可变长度编码,这意味着小值使用更少的空间;所以0-127取1字节加上报头。请注意,varint本身对于负数来说是非常循环的,因此也支持“之字形”编码,这允许小数量级的数字变小(基本上,它交错正负对)

实际上,对于
分数
的情况,您还应该考虑“打包”编码,它需要
[ProtoMember(4,IsPacked=true)]
或通过v2中的
类型模型
实现的等效编码(v2支持任何一种方法)。通过写入单个标头和组合长度,可以避免每个值的标头开销。“打包”可与varint/zigzag一起使用。对于您知道值可能很大且不可预测的场景,也有固定长度的编码

另外请注意:如果您的数据包含大量文本,您可以通过gzip或deflate额外运行它;如果没有,那么gzip和deflate都可能导致它变大


wire格式概述;理解它并不是很难,并且可以帮助您计划如何进一步优化。

< P>至少C++库确实支持对压缩流的写入:


但我不确定是否已将其移植到.Net实现中。

为什么protobuf仅为128个值生成1个字节?8位允许写入256个不同的值。@tobi它对字段号使用“varint”编码,这意味着7位有效负载,1位“还有一个字节要读取”。继续读取,直到MSB为零。在.NET中,只需将任何序列化程序连接到实例,然后:完成