I have started work with protobuf-net library. It increased speed of serialization on 30% but I have troubles with resulting file size.
My data model is:
[Serializable]
[ProtoContract(SkipConstructor = true)]
private class ReportDataItem
{
[ProtoMember(1)]
public Int32 C11 { get; set; }
[ProtoMember(2)]
public Int32 C12 { get; set; }
[ProtoMember(3)]
public Int32 C13 { get; set; }
[ProtoMember(4)]
public Int32 C14 { get; set; }
[ProtoMember(5)]
public Int32 C15 { get; set; }
[ProtoMember(6)]
public Int32 C16 { get; set; }
[ProtoMember(7)]
public Int32 C17 { get; set; }
[ProtoMember(8)]
public Int32 C18 { get; set; }
[ProtoMember(9)]
public Int32 C19 { get; set; }
[ProtoMember(10)]
public Int32 C110 { get; set; }
[ProtoMember(11)]
public Int64 C21 { get; set; }
[ProtoMember(12)]
public Int64 C22 { get; set; }
[ProtoMember(13)]
public Int64 C23 { get; set; }
[ProtoMember(14)]
public Int64 C24 { get; set; }
[ProtoMember(15)]
public Int64 C25 { get; set; }
[ProtoMember(16)]
public Int64 C26 { get; set; }
[ProtoMember(17)]
public Int64 C27 { get; set; }
[ProtoMember(18)]
public Int64 C28 { get; set; }
[ProtoMember(19)]
public Int64 C29 { get; set; }
[ProtoMember(20)]
public Int64 C210 { get; set; }
[ProtoMember(21)]
public String C31 { get; set; }
[ProtoMember(22)]
public String C32 { get; set; }
[ProtoMember(23)]
public String C33 { get; set; }
[ProtoMember(24)]
public String C34 { get; set; }
[ProtoMember(25)]
public String C35 { get; set; }
[ProtoMember(26)]
public String C36 { get; set; }
[ProtoMember(27)]
public String C37 { get; set; }
[ProtoMember(28)]
public String C38 { get; set; }
[ProtoMember(29)]
public String C39 { get; set; }
[ProtoMember(30)]
public String C310 { get; set; }
}
[Serializable]
[ProtoContract()]
private class ReportData
{
[ProtoMember(1, DataFormat = DataFormat.Group)]
public List<ReportDataItem> ReportDataItems { get; set; }
}
[Serializable]
[ProtoContract()]
private class Report
{
[ProtoMember(1)]
public ReportData ReportData { get; set; }
}
So when I try to serialize:
private static void ObjectSerialization()
{
const string someData = @”qtwretyfsjdabvfsjdlfudspogds;kfg;lkfdsl;gkl;dsfkgl;kdfsgr;iweprpo\z\xlvcfmxzcbvjiorsdifdlf\jl;dsa”;
Report report = new Report();
report.ReportData = new ReportData {ReportDataItems = new List<ReportDataItem>()};
for (int j = 0; j < 10; j++)
{
ReportDataItem reportDataItem = new ReportDataItem();
reportDataItem.C11 = j;
reportDataItem.C12 = j;
reportDataItem.C13 = j;
reportDataItem.C14 = j;
reportDataItem.C15 = j;
reportDataItem.C16 = j;
reportDataItem.C17 = j;
reportDataItem.C18 = j;
reportDataItem.C19 = j;
reportDataItem.C110 = j;
reportDataItem.C21 = j;
reportDataItem.C22 = j;
reportDataItem.C23 = j;
reportDataItem.C24 = j;
reportDataItem.C25 = j;
reportDataItem.C26 = j;
reportDataItem.C27 = j;
reportDataItem.C28 = j;
reportDataItem.C29 = j;
reportDataItem.C210 = j;
reportDataItem.C31 =someData;
reportDataItem.C32 = someData;
reportDataItem.C33 = someData;
reportDataItem.C34 = someData;
reportDataItem.C35 = someData;
reportDataItem.C36 = someData;
reportDataItem.C37 = someData;
reportDataItem.C38 = someData;
reportDataItem.C39 = someData;
reportDataItem.C310 = someData;
report.ReportData.ReportDataItems.Add(reportDataItem);
}
using (Stream stream = new FileStream(@"c:\Test\Object\0.bin", FileMode.Create, FileAccess.Write, FileShare.Write))
{
Serializer.Serialize(stream, report);
}
using (Stream stream = new FileStream(@"c:\Test\Object\bf_0.bin", FileMode.Create, FileAccess.Write, FileShare.Write))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, report);
}
}
I had results provided below:
- protobuf-net file size 10428 Bytes
- BinaryFormatter file size 3458 Bytes
Could you help me to find a right solution for decrease a size of result protobuf-net file.
Protobuf-net I installed as a package from VS Package Manager.
I changed the last few lines to:
to get the amount of data written to the stream, and the final size of the files. My results:
Which looks fine to me. Please verify your data.
Is it possible that you are using a much bigger string than “some data”? If so, there is an important question: are you likely to be duplicating the strings in real code? If you aren’t, then the BF test is invalid, because it will be using reference tracking by default, so only storing the strings once – but your real data will behave very differently. If you are going to be using the same string lots of times, then you can mimic this re-use in protobuf-net:
The output now:
However! This will slightly grow the output if the strings are not generally repeated, and will make it hard for other protobuf implementations to use it (it is valid protobuf data, but via some voodoo).
The above is useful if, for example, you have things like custom names / country names / statuses etc that are represented as strings but duplicated lots.