BinaryFormatter
とprotobuf-netシリアライザーを比較していて、私が found であることに非常に満足していましたが、奇妙なことに、protobuf-netがオブジェクトをより小さなものにシリアル化できました。すべてのプロパティの値をメタデータなしでバイトの配列に書き込んだ場合よりもバイト配列。
AsReference
をtrue
に設定すると、protobuf-netが文字列インターンをサポートすることは知っていますが、この場合はサポートしていません。protobuf-netはデフォルトで圧縮を提供しますか?
自分で確認するために実行できるコードは次のとおりです。
var simpleObject = new SimpleObject
{
Id = 10,
Name = "Yan",
Address = "Planet Earth",
Scores = Enumerable.Range(1, 10).ToList()
};
using (var memStream = new MemoryStream())
{
var binaryWriter = new BinaryWriter(memStream);
// 4 bytes for int
binaryWriter.Write(simpleObject.Id);
// 3 bytes + 1 more for string termination
binaryWriter.Write(simpleObject.Name);
// 12 bytes + 1 more for string termination
binaryWriter.Write(simpleObject.Address);
// 40 bytes for 10 ints
simpleObject.Scores.ForEach(binaryWriter.Write);
// 61 bytes, which is what I expect
Console.WriteLine("BinaryWriter wrote [{0}] bytes",
memStream.ToArray().Count());
}
using (var memStream = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(memStream, simpleObject);
// 41 bytes!
Console.WriteLine("Protobuf serialize wrote [{0}] bytes",
memStream.ToArray().Count());
}
編集:追加するのを忘れた、SimpleObject
クラスは次のようになります:
[Serializable]
[DataContract]
public class SimpleObject
{
[DataMember(Order = 1)]
public int Id { get; set; }
[DataMember(Order = 2)]
public string Name { get; set; }
[DataMember(Order = 3)]
public string Address { get; set; }
[DataMember(Order = 4)]
public List<int> Scores { get; set; }
}
いいえ、違います; protobuf仕様で指定されているような「圧縮」はありません。ただし、(デフォルトでは)「varintencoding」を使用します。これは整数データの可変長エンコーディングであり、値が小さいほどスペースの使用量が少なくなります。したがって、0-127は1バイトとヘッダーを取ります。 varint自体は負の数に対してかなりループするため、小さいを許可する「ジグザグ」エンコーディングもサポートされていることに注意してください。マグニチュードの数値を小さくします(基本的に、正と負のペアをインターリーブします)。
実際、Scores
の場合は、「パックされた」エンコーディングも確認する必要があります。これには、[ProtoMember(4, IsPacked = true)]
またはv2のTypeModel
を介した同等のものが必要です(v2はどちらのアプローチもサポートします) 。これにより、単一のヘッダーとcombinedの長さを書き込むことにより、値ごとのヘッダーのオーバーヘッドが回避されます。 「パック」は、varint/zigzagで使用できます。値が大きくて予測できない可能性が高い知っているシナリオ用の固定長エンコーディングもあります。
注:ただし、データに大量のテキストが含まれている場合は、gzipまたはdeflateを使用してデータを追加で実行するとメリットが得られる場合があります。 しない場合、gzipとdeflateの両方で大きくなる可能性があります。
ワイヤーフォーマットの概要 ここにあります ;理解するのはそれほど難しいことではなく、さらに最適化するための最善の方法を計画するのに役立つ場合があります。