Ne protobuf-net ont de compression intégré pour la sérialisation?
Je faisais une comparaison entre BinaryFormatter
et protobuf-net sérialiseur et a été très heureux avec ce que j'ai trouvé, mais ce qui était étrange, c'est que protobuf-net réussi à sérialiser les objets dans un petit tableau d'octets que ce que je voudrais faire si j'ai juste écrit la valeur de chaque propriété dans un tableau d'octets sans métadonnées.
Je sais protobuf-net prend en charge la chaîne de stage si vous définissez AsReference
à true
, mais je ne fais pas que dans ce cas, le fait de protobuf-net fournir certains de compression par défaut?
Voici un code que vous pouvez exécuter pour voir par vous-même:
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());
}
EDIT: oublié de l'ajouter, le SimpleObject
classe ressemble à ceci:
[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; }
}
Vous devez vous connecter pour publier un commentaire.
Non, il ne fonctionne pas; il n'y a pas de "compression" tel que spécifié dans la protobuf spec; toutefois, il n' (par défaut) utiliser "varint encodage" - variable-length encoding (encodage de données entier qui désigne les petites valeurs d'utiliser moins d'espace; de sorte 0-127 prendre 1 octet de plus que l'en-tête. Notez que varint par lui-même va assez cinglé pour les nombres négatifs, ce "zigzag" encoding est également pris en charge qui permet aux petites ampleur nombres à petit (en gros, il entrelace positifs et négatifs paires).
Effectivement, dans votre cas pour
Scores
vous devriez également regarder les "paniers" encodage, ce qui nécessite soit[ProtoMember(4, IsPacked = true)]
ou l'équivalent viaTypeModel
en v2 (v2 prend en charge une ou l'autre approche). Cela permet d'éviter la surcharge d'un en-tête par valeur, par l'écriture d'une seule tête et le combiné longueur. "Emballé" peut être utilisé avec varint/zigzag. Il y a aussi de longueur fixe les codages pour les scénarios où vous savoir les valeurs sont probablement importantes et imprévisibles.Noter également: mais si vos données a beaucoup de texte vous pouvez bénéficier en outre de course à travers gzip ou deflate; si elle n'est pas, puis les deux gzip et deflate pourrait causer plus gros.
Un aperçu du format de câble est ici; il n'est pas très difficile à comprendre, et peut vous aider à planifier la meilleure façon de continuer à optimiser.