【问题标题】:How to calculate protobuf file size?如何计算 protobuf 文件大小?
【发布时间】:2017-03-01 10:23:10
【问题描述】:

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

我用不同的 proto 配置和二进制序列化做了一些比较测试,但我仍然不明白“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 长度 = 30 字节

2) testFullPt3D.pb 长度 = 27 字节

3) testBinaryWriter.bin 长度 = 24 字节

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 长度 = 29 字节

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

结果:testPt3D.pb 长度 = 30 字节

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

结果:testPt3D.pb 长度 = 30 字节

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

为什么我使用 21、101 或 1111 得到相同的尺寸?

【问题讨论】:

标签: c# protobuf-net


【解决方案1】:

1) testPt3D.pb 长度 = 30 字节

  • (子类在前)[字段 101,字符串] = 2 个字节,“字符串”3 位,“101”7 位; varint 以 7 位单元打包,并带有一个连续位,因此:2 个字节(总计 = 2)
    • [数据长度“9”] = 1 字节(总计 = 3)
    • [字段 1,固定 64] = 1 字节(总计 = 4)
    • [有效负载 1] = 8 字节(总计 = 12)
  • [字段 1,固定 64] = 1 字节(总计 = 13)
  • [有效负载 1] = 8 字节(总计 = 21)
  • [字段 2,固定 64] = 1 字节(总计 = 22)
  • [有效负载 2] = 8 字节(总计 = 30)

2) testFullPt3D.pb 长度 = 27 字节

  • [字段 1,固定 64] = 1 字节(总计 = 1)
  • [有效负载 1] = 8 字节(总计 = 9)
  • [字段 2,固定 64] = 1 字节(总计 = 10)
  • [有效负载 2] = 8 字节(总计 = 18)
  • [字段 3,固定 64] = 1 字节(总计 = 19)
  • [有效负载 3] = 8 字节(总计 = 27)

在处理重复数据时,protobuf中还有其他选项——“打包”和“分组”;不过,只有在讨论更多个数据而不是 3 个值时,它们才有意义。

【讨论】:

  • 感谢解释,但是我用来标识字段或子类的索引值不影响大小? (请参阅我的最后一个问题 - 为什么我使用 21、101 或 1111 得到相同的尺寸?)
  • @ilCosmico 字段编号被打包成 7 位的块,但是第一个字节的 3 位已经被占用(对于有线类型) - 只有 4 位第一个块可供使用。因此,您只能获得 1-15(4 位)的单字节标记;之后,使用下一个 7 位块,我们得到 5-11 位的 2 字节标记(字段 16-2047)。因此,由于您选择的所有数字都在 16-2047 范围内,因此它们都占用 2 个字节。如果您选择“3”,则需要 1 个字节。如果您选择“2500”,它将占用 3 个字节。
  • 最后一个疑问,[数据长度“9”] = 1字节究竟是什么?
  • @ilCosmico 它正在编码后面数据的长度,即 9 个字节;为此,它使用“varint”编码对9 进行编码,该编码占用一个字节(值 0x09)
猜你喜欢
  • 2011-01-12
  • 2012-11-13
  • 2010-10-12
  • 1970-01-01
  • 2014-07-23
  • 2011-08-17
  • 2011-11-24
相关资源
最近更新 更多