如何计算protobuf文件大小?

时间:2017-03-01 10:23:11

标签: c# protobuf-net

我正在试图找出使用protobuf-net序列化的文件的最终大小,因此我可以选择最佳方法。

我使用不同的原型配置和二进制序列化进行了一些比较测试,但我仍然不明白“varint to bytes”转换是如何工作的。

public class Pt2D
{
    public Pt2D() { }

    public Pt2D(double x, double y)
    {
        X = x;
        Y = y;
    }
    public double X { get; set; }

    public double Y { get; set; }
}

public class Pt3D : Pt2D
{
    public Pt3D() { }

    public Pt3D(double x, double y, double z) : base(x, y)
    {
        Z = z;
    }
    public double Z { get; set; }
}

public class FullPt3D
{
    public FullPt3D() { }

    public FullPt3D(double x, double y, double z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public double X { get; set; }

    public double Y { get; set; }

    public double Z { get; set; }
}

测试用例

private void ProtoBufferTest()
{            
    var model = RuntimeTypeModel.Default;

    model.Add(typeof(Pt2D), false)
        .Add(1, "X")
        .Add(2, "Y")
        .AddSubType(101, typeof(Pt3D));

    model[typeof(Pt3D)]
        .Add(1, "Z");

    model.Add(typeof(FullPt3D), false)
        .Add(1, "X")
        .Add(2, "Y")
        .Add(3, "Z");

    double x = 5.6050692524784562;
    double y = 0.74161805247031987;
    double z = 8.5883424750474937;

    string filename = "testPt3D.pb";
    using (var file = File.Create(filename))
    {
        Serializer.Serialize(file, new Pt3D(x, y, z));                               
    }
    Console.WriteLine(filename + " length = " + new FileInfo(filename).Length + " bytes") ;

    filename = "testFullPt3D.pb";
    using (var file = File.Create(filename))
    {
        Serializer.Serialize(file, new FullPt3D(x, y, z));                
    }
    Console.WriteLine(filename + " length = " + new FileInfo(filename).Length + " bytes");

    filename = "testBinaryWriter.bin";
    using (var file = File.Create(filename))
    {
        using (var writer = new BinaryWriter(file))
        {                
            writer.Write(x);
            writer.Write(y);
            writer.Write(z);
        }

    }
    Console.WriteLine(filename + " length = " + new FileInfo(filename).Length + " bytes");


}    

测试结果

1)testPt3D.pb length = 30 bytes

2)testFullPt3D.pb length = 27 bytes

3)testBinaryWriter.bin length = 24 bytes

Q1) 24个字节用于存储3个双精度值,没关系,但是在1)和2)情况下存储的值是多少来达到30和27个字节? (我假设模型映射中使用的int值)

Q2)我通过更改Pt2D的SubType映射进行了一些测试,但我无法理解尺寸变化

model.Add(typeof(Pt2D), false)
        .Add(1, "X")
        .Add(2, "Y")
        .AddSubType(3, typeof(Pt3D));

结果:testPt3D.pb length = 29 bytes

model.Add(typeof(Pt2D), false)
        .Add(1, "X")
        .Add(2, "Y")
        .AddSubType(21, typeof(Pt3D));

结果:testPt3D.pb length = 30 bytes

model.Add(typeof(Pt2D), false)
        .Add(1, "X")
        .Add(2, "Y")
        .AddSubType(1111, typeof(Pt3D));

结果:testPt3D.pb length = 30 bytes

我尝试使用this tool来更好地理解,但它提供了不同的字节转换结果。

为什么我使用21,101或1111获得相同的大小?

1 个答案:

答案 0 :(得分:1)

1)testPt3D.pb length = 30 bytes

  • (子类首先出现)[字段101,字符串] = 2字节,3位用于"字符串",7位用于" 101&#34 ;; varint包以7位为单位,带有一个连续位,所以:2个字节(总数= 2)
    • [数据长度" 9"] = 1字节(总计= 3)
    • [字段1,固定64] = 1字节(总计= 4)
    • [payload 1] = 8个字节(total = 12)
  • [字段1,固定64] = 1字节(总计= 13)
  • [payload 1] = 8个字节(total = 21)
  • [字段2,固定64] = 1字节(总计= 22)
  • [payload 2] = 8个字节(总计= 30)

2)testFullPt3D.pb length = 27 bytes

  • [字段1,固定64] = 1字节(总计= 1)
  • [payload 1] = 8个字节(total = 9)
  • [字段2,固定64] = 1字节(总计= 10)
  • [payload 2] = 8个字节(total = 18)
  • [字段3,固定64] = 1字节(总计= 19)
  • [payload 3] = 8个字节(总计= 27)

在处理重复数据时,protobuf还有其他选项 - "打包"和"分组&#34 ;;但是,在讨论更多数据时,它们才有意义,而不是3个值。