2017-03-01 61 views
1

我想弄清楚用protobuf-net序列化的文件的最終大小,所以我可以選擇最好的方法。如何計算protobuf文件大小?

我做了不同的原型配置和二進制序列化的比較測試,但我仍然不明白「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亞型映射進行了一些測試,但我不理解的大小改變

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可以獲得相同的尺寸?

+0

還有這方面的線索嗎? :( – ilCosmico

回答

1

1)testPt3D。pb長度= 30字節

  • (子類優先)[字段101,字符串] = 2字節,3位爲「字符串」,7位爲「101」; 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 b YTE(總= 19)
  • [淨荷3] = 8個字節(總= 27)

反覆數據處理時,有在protobuf的其他選項 - 「打包」 和 「分組」;但只有在討論更多數據時,它們纔有意義。

+0

感謝您的解釋,但我用來確定字段或子類的索引值不會影響大小?(請參閱我的最後一個問題 - 爲什麼使用21,101或1111獲得相同的大小?) – ilCosmico

+0

@ ilCosmico字段編號以7位塊打包**,但是第一個字節的** 3位已經被採用(對於線型) - 第一個塊只有4位可用,所以你只能得到單字節標記爲1-15(4比特);之後,使用下一個7比特的塊,我們得到5-11比特的兩個字節的標記(字段16-2047)。因此,由於所有你選擇的數字是在16-2047範圍內,它們全部需要2個字節,如果選擇「3」則需要1個字節,如果選擇「2500」則需要3個字節。 –

+0

再次感謝,現在更清楚:) – ilCosmico