1

protobuf-net ライブラリの使用を開始しました。シリアル化の速度が 30% 向上しましたが、結果のファイル サイズに問題があります。

私のデータモデルは次のとおりです。

    [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; }
    }

したがって、シリアル化しようとすると:

    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);
            }
}

以下に結果を示しました。

  • protobuf-netファイル サイズ10428 バイト
  • BinaryFormatterファイル サイズ3458 バイト

結果のprotobuf-netファイルのサイズを減らすための適切な解決策を見つけるのを手伝ってくれませんか. Protobuf-net VS Package Manager からパッケージとしてインストールしました。

4

1 に答える 1

2

最後の数行を次のように変更しました。

using (Stream stream = new FileStream(@"pb.bin", FileMode.Create,
     FileAccess.Write, FileShare.Write))
{
    Serializer.Serialize(stream, report);
    Console.WriteLine(stream.Length);
}
Console.WriteLine(new FileInfo("pb.bin").Length);

using (Stream stream = new FileStream(@"bf.bin", FileMode.Create,
     FileAccess.Write, FileShare.Write))
{
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, report);
    Console.WriteLine(stream.Length);
}
Console.WriteLine(new FileInfo("bf.bin").Length);

ストリームに書き込まれたデータの量と、ファイルの最終的なサイズを取得します。私の結果:

1628
1628
3144
3144

それは私にはうまく見えます。データを確認してください。

「一部のデータ」よりもはるかに大きな文字列を使用している可能性はありますか? もしそうなら、重要な質問があります: 実際のコードで文字列を複製する可能性はありますか? そうでない場合、BF テストは無効です。これは、デフォルトで参照追跡を使用するため、文字列を 1 回だけ保存するためですが、実際のデータの動作は大きく異なります。同じ文字列を何度も使用する場合、protobuf-net でこの再利用を模倣できます。

[ProtoMember(21, AsReference=true)]
public String C31 { get; set; }
[ProtoMember(22, AsReference = true)]
public String C32 { get; set; }
[ProtoMember(23, AsReference = true)]
public String C33 { get; set; }
[ProtoMember(24, AsReference = true)]
public String C34 { get; set; }
[ProtoMember(25, AsReference = true)]
public String C35 { get; set; }
[ProtoMember(26, AsReference = true)]
public String C36 { get; set; }
[ProtoMember(27, AsReference = true)]
public String C37 { get; set; }
[ProtoMember(28, AsReference = true)]
public String C38 { get; set; }
[ProtoMember(29, AsReference = true)]
public String C39 { get; set; }
[ProtoMember(30, AsReference = true)]
public String C310 { get; set; }

出力は次のとおりです。

939
939
3144
3144

でも!文字列が一般的に繰り返されない場合、これにより出力がわずかに大きくなり、他の protobuf 実装がそれを使用するのが難しくなります (これは有効な protobuf データですが、いくつかのブードゥーを介して)。

上記は、たとえば、文字列として表されているがロットが重複しているカスタム名/国名/ステータスなどがある場合に役立ちます。

于 2013-01-28T13:12:20.577 に答える