如何计算 protobuf 文件大小?
How to calculate protobuf file size?
我正在尝试计算使用 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 长度 = 30 字节
2) testFullPt3D.pb 长度 = 27 字节
3) testBinaryWriter.bin 长度 = 24 字节
Q1) 3个double值用24个字节存储没问题,但是情况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 得到相同的尺寸?
1) testPt3D.pb 长度 = 30 字节
- (subclass comes first) [field 101, string] = 2 bytes, 3 bits for "string", 7 bits for "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 个字节(总计 = 19)
- [有效负载 3] = 8 字节(总计 = 27)
在处理重复数据时,protobuf 中还有其他选项 - "packed" 和 "grouped";不过,它们只有在讨论 比 3 个值更多 的数据时才有意义。
我正在尝试计算使用 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 长度 = 30 字节
2) testFullPt3D.pb 长度 = 27 字节
3) testBinaryWriter.bin 长度 = 24 字节
Q1) 3个double值用24个字节存储没问题,但是情况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 得到相同的尺寸?
1) testPt3D.pb 长度 = 30 字节
- (subclass comes first) [field 101, string] = 2 bytes, 3 bits for "string", 7 bits for "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 个字节(总计 = 19)
- [有效负载 3] = 8 字节(总计 = 27)
在处理重复数据时,protobuf 中还有其他选项 - "packed" 和 "grouped";不过,它们只有在讨论 比 3 个值更多 的数据时才有意义。