简介

MessagePack for C#(MessagePack-CSharp)是用于C#的极速MessagePack序列化程序,比MsgPack-Cli快10倍,与其他所有C#序列化程序相比,具有最好的性能。 MessagePack for C#具有内置的LZ4压缩功能,可以实现超快速序列化和二进制占用空间小。 性能永远是重要的! 可用于游戏,分布式计算,微服务,数据存储到Redis等。支持.NET, .NET Core, Unity, Xamarin。

从上图我们看出MessagePack for C#在性能测试中是最好的,这里解释一下第三个MsgPack-Cli是MessagePack官方实现的。第一和第二都是MessagePack for C#,第一项相比第二项具有稍快一点的序列化和反序列化速度,但是第二项采用了L4压缩功能,显著的减少了二进制的大小。在实际使用中推荐使用L4压缩功能。

使用

该组件已经发布在Nuget,使用命令加入项目。

Install-Package MessagePack

分析器

Install-Package MessagePackAnalyzer

扩展

Install-Package MessagePack.ImmutableCollection
Install-Package MessagePack.ReactiveProperty
Install-Package MessagePack.UnityShims
Install-Package MessagePack.AspNetCoreMvcFormatter

Unity在此处下载 https://github.com/neuecc/MessagePack-CSharp/releases

快速开始

定义一个类添加[MessagePackObject]特性,公共成员(属性或者字段)添加[Key]特性,调用MessagePackSerializer.Serialize<T>/Deserialize<T>进行序列化和反序列化,ToJson可以帮我们转储二进制为json格式。

// 标记 MessagePackObjectAttribute
[MessagePackObject]
public class MyClass
{
// Key 是序列化索引,对于版本控制非常重要。
[Key(0)]
public int Age { get; set; } [Key(1)]
public string FirstName { get; set; } [Key(2)]
public string LastName { get; set; } // 公共成员中不序列化目标,标记IgnoreMemberAttribute
[IgnoreMember]
public string FullName { get { return FirstName + LastName; } }
}
class Program
{
static void Main(string[] args)
{
var mc = new MyClass
{
Age = 99,
FirstName = "hoge",
LastName = "huga",
}; // 序列化
var bytes = MessagePackSerializer.Serialize(mc);
//反序列化
var mc2 = MessagePackSerializer.Deserialize<MyClass>(bytes); // 你可以将msgpack二进制转储为可读的json。
// 在默认情况下,MeesagePack for C#减少了属性名称信息。
// [99,"hoge","huga"]
var json = MessagePackSerializer.ToJson(bytes);
Console.WriteLine(json); Console.ReadKey(); }
}

序列化索引将会影响该信息在序列化数据中的位置

默认情况下特性是必须的,但是我们有方法进行改变,让它变为不是必须的,详情请看后面。

分析器

MessagePackAnalyzer 可以帮助我们定义对象. 如果不符合规则,那么特性, 程序集等可以被检测到,如果我们编译就会出现编译错误。

如果要允许特定类型(例如,注册自定义类型时),请将MessagePackAnalyzer.json放在项目根目录下,并将生成操作设置为AdditionalFiles(其他文件)。

这是MessagePackAnalyzer.json内容的一个示例。

[ "MyNamespace.FooClass", "MyNameSpace.BarStruct" ]

内置的支持类型

这些类型可以默认序列化。

基元(int、string等等), Enum, Nullable<>, TimeSpan, DateTime, DateTimeOffset, Nil, Guid, Uri, Version, StringBuilder, BitArray, ArraySegment<>, BigInteger, Complext, Task, Array[], Array[,], Array[,,], Array[,,,], KeyValuePair<,>, Tuple<,...>, ValueTuple<,...>, List<>, LinkedList<>, Queue<>, Stack<>, HashSet<>, ReadOnlyCollection<>, IList<>, ICollection<>, IEnumerable<>, Dictionary<,>, IDictionary<,>, SortedDictionary<,>, SortedList<,>, ILookup<,>, IGrouping<,>, ObservableCollection<>, ReadOnlyOnservableCollection<>, IReadOnlyList<>, IReadOnlyCollection<>, ISet<>, ConcurrentBag<>, ConcurrentQueue<>, ConcurrentStack<>, ReadOnlyDictionary<,>, IReadOnlyDictionary<,>, ConcurrentDictionary<,>, Lazy<>, Task<>, 自定义继承ICollection <>或IDictionary <,>具有无参构造方法, IList,IDictionary和自定义继承ICollection或IDictionary具有无参构造函数(包括ArrayList和Hashtable)。

您可以添加自定义类型的支持和一些官方/第三方扩展包。 对于ImmutableCollections(ImmutableList <>等),对于ReactiveProperty和Unity(Vector3, Quaternion等等),对于F#(Record,FsList,Discriminated Unions等)。

MessagePack.Nil是MessagePack for C#的内置null/void/unit表示类型。

对象序列化

MessagePack for C#可以序列化public Class或Struct,序列化目标必须标记[MessagePackObject]和[Key], Key类型可以选择int或字符串。如果Key类型是int,则使用序列化格式为数组,如果Key类型是字符串,则使用序列化格式为键值对,如果您定义了[MessagePackObject(keyAsPropertyName:true)],则不需要Key特性。

[MessagePackObject]
public class Sample1
{
[Key(0)]
public int Foo { get; set; }
[Key(1)]
public int Bar { get; set; }
} [MessagePackObject]
public class Sample2
{
[Key("foo")]
public int Foo { get; set; }
[Key("bar")]
public int Bar { get; set; }
} [MessagePackObject(keyAsPropertyName: true)]
public class Sample3
{
// 不需要key特性
public int Foo { get; set; } // 不需要序列化的成员使用IgnoreMember特性
[IgnoreMember]
public int Bar { get; set; }
} // 结果 [10,20]
Console.WriteLine(MessagePackSerializer.ToJson(new Sample1 { Foo = 10, Bar = 20 })); // 结果 {"foo":10,"bar":20}
Console.WriteLine(MessagePackSerializer.ToJson(new Sample2 { Foo = 10, Bar = 20 })); // 结果 {"Foo":10}
Console.WriteLine(MessagePackSerializer.ToJson(new Sample3 { Foo = 10, Bar = 20 }));

所有模式序列化目标都是公共实例成员(字段或属性)。 如果要避免序列化目标,可以将[IgnoreMember]添加到目标成员。

目标类必须是 public, 不允许 private, internal 类.

应该使用哪种Key类型,int或string? 作者建议使用int key,因为比string key更快,更紧凑。 但是string key有关键的名字信息,对调试很有用。

MessagePackSerializer序列化目标时,必须在目标使用特性才能保证稳健性,如果类进行了扩充,你必须意识到版本控制。如果Key不存在,MessagePackSerializer将会使用默认值。如果使用的是int key,那么必须从0开始,如果不必要的属性出现,请填写空缺的数字。重用是不好的。 此外,如果Int Key的跳转数字差距太大,则会影响二进制大小。

[MessagePackObject]
public class IntKeySample
{
[Key(3)]
public int A { get; set; }
[Key(10)]
public int B { get; set; }
} // int key不从0开始并且数字进行了跳跃,将会出现下面的结果
//[null,null,null,0,null,null,null,null,null,null,0]
Console.WriteLine(MessagePackSerializer.ToJson(new IntKeySample()));

如果你想像JSON.NET那样使用!不想加特性! 如果你这样想,你可以使用无约定的解析器。

public class ContractlessSample
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
} var data = new ContractlessSample { MyProperty1 = 99, MyProperty2 = 9999 };
var bin = MessagePackSerializer.Serialize(data, MessagePack.Resolvers.ContractlessStandardResolver.Instance); // {"MyProperty1":99,"MyProperty2":9999}
Console.WriteLine(MessagePackSerializer.ToJson(bin)); // 全局设置无约束解析器为默认解析器
MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance); // 序列化
var bin2 = MessagePackSerializer.Serialize(data);

我想序列化私人成员! 默认情况下,不能序列化/反序列化私有成员。 但是你可以使用allow-private解析器来序列化私人成员。

[MessagePackObject]
public class PrivateSample
{
[Key(0)]
int x; public void SetX(int v)
{
x = v;
} public int GetX()
{
return x;
}
} var data = new PrivateSample();
data.SetX(9999); // 你可以选择 StandardResolverAllowPrivate 或者 ContractlessStandardResolverAllowPrivate 解析器
var bin = MessagePackSerializer.Serialize(data, MessagePack.Resolvers.DynamicObjectResolverAllowPrivate.Instance);

我不需要类型,我想像BinaryFormatter那样使用! 你可以使用无类型的解析器和帮助器。 请参阅Typeless部分。

解析器是MessagePack For C#的关键定制点。 详情请见扩展部分。

DataContract兼容性

您可以使用[DataContract]而不是[MessagePackObject]。 如果type标记为DataContract,则可以使用[DataMember]代替[Key],[IgnoreDataMember]代替[IgnoreMember]。

[DataMember(Order = int)] 和 [Key(int)]相同, [DataMember(Name = string)]和 [Key(string)]相同. 如果使用 [DataMember], 则类似于 [Key(nameof(propertyname)].

使用DataContract使其成为一个共享的类库,您不必引用MessagePack for C#。 但是,它不包含在分析器或由mpc.exe生成的代码中。此外,像UnionAttribute,MessagePackFormatterAttribute,SerializationConstructorAttribute等功能不能使用。 出于这个原因,我建议您基本上使用MessagePack for C#特性。

序列化不可变对象(序列化构造器)

MessagePack for C#支持反序列化不可变对象。 例如,这个struct可以自然地序列化/反序列化。

[MessagePackObject]
public struct Point
{
[Key(0)]
public readonly int X;
[Key(1)]
public readonly int Y; public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
} var data = new Point(99, 9999);
var bin = MessagePackSerializer.Serialize(data); // Okay to deserialize immutable obejct
var point = MessagePackSerializer.Deserialize<Point>(bin);

MessagePackSerializer choose constructor with the least matched argument, match index if key in integer or match name(ignore case) if key is string. If encounts MessagePackDynamicObjectResolverException: can't find matched constructor parameter you should check about this.

MessagePackSerializer选择具有最少参数的构造方法,如果key是整型将匹配索引或者如果key是字符串将匹配名称(忽略大小写)。 如果遇到 MessagePackDynamicObjectResolverException: can't find matched constructor parameter 你应该检查一会下。

如果不能自动匹配,可以通过[SerializationConstructorAttribute]手动指定使用构造函数。

[MessagePackObject]
public struct Point
{
[Key(0)]
public readonly int X;
[Key(1)]
public readonly int Y; // 如果没有标记特性,将会使用这方法(最少参数)
public Point(int x)
{
X = x;
} [SerializationConstructor]
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
}

序列化回调

如果对象实现了IMessagePackSerializationCallbackReceiver,则接受OnBeforeSerializeOnAfterDeserialize序列化处理。

[MessagePackObject]
public class SampleCallback : IMessagePackSerializationCallbackReceiver
{
[Key(0)]
public int Key { get; set; } public void OnBeforeSerialize()
{
Console.WriteLine("OnBefore");
} public void OnAfterDeserialize()
{
Console.WriteLine("OnAfter");
}
}

Union

MessagePack for C#支持序列化接口。这就像XmlInclude或ProtoInclude。在MessagePack for C#里叫Union。UnionAttribute只能附加到接口或抽象类。 它需要区分的整型key和子类型

// mark inheritance types
[MessagePack.Union(0, typeof(FooClass))]
[MessagePack.Union(1, typeof(BarClass))]
public interface IUnionSample
{
} [MessagePackObject]
public class FooClass : IUnionSample
{
[Key(0)]
public int XYZ { get; set; }
} [MessagePackObject]
public class BarClass : IUnionSample
{
[Key(0)]
public string OPQ { get; set; }
} // --- IUnionSample data = new FooClass() { XYZ = 999 }; // serialize interface.
var bin = MessagePackSerializer.Serialize(data); // deserialize interface.
var reData = MessagePackSerializer.Deserialize<IUnionSample>(bin); // use type-switch of C# 7.0
switch (reData)
{
case FooClass x:
Console.WriteLine(x.XYZ);
break;
case BarClass x:
Console.WriteLine(x.OPQ);
break;
default:
break;
}

C#7.0 type-switch是Union的最佳选择。 Union被序列化为两个长度的数组。

IUnionSample data = new BarClass { OPQ = "FooBar" };

var bin = MessagePackSerializer.Serialize(data);

// Union is serialized to two-length array, [key, object]
// [1,["FooBar"]]
Console.WriteLine(MessagePackSerializer.ToJson(bin));

在抽象类中使用Union,你可以像接口那样使用。

[Union(0, typeof(SubUnionType1))]
[Union(1, typeof(SubUnionType2))]
[MessagePackObject]
public abstract class ParentUnionType
{
[Key(0)]
public int MyProperty { get; set; }
} [MessagePackObject]
public class SubUnionType1 : ParentUnionType
{
[Key(1)]
public int MyProperty1 { get; set; }
} [MessagePackObject]
public class SubUnionType2 : ParentUnionType
{
[Key(1)]
public int MyProperty2 { get; set; }
}

继承类型的序列化,在数组(或键值对)中是扁平化的,对于整型键是无关紧要的,它不能复制父类和所有的子类。

Dynamic(Untyped)反序列化

如果使用MessagePackSerializer.Deserialize<object> 或者 MessagePackSerializer.Deserialize<dynamic>,messagepack将转换为 primitive values,msgpack-primitive将转换为 bool, char, sbyte, byte, short, int, long, ushort, uint, ulong, float, double, DateTime, string, byte[], object[], IDictionary<object, object>.

// sample binary.
var model = new DynamicModel { Name = "foobar", Items = new[] { 1, 10, 100, 1000 } };
var bin = MessagePackSerializer.Serialize(model, ContractlessStandardResolver.Instance); // dynamic, untyped
var dynamicModel = MessagePackSerializer.Deserialize<dynamic>(bin, ContractlessStandardResolver.Instance); Console.WriteLine(dynamicModel["Name"]); // foobar
Console.WriteLine(dynamicModel["Items"][2]); // 100

所以你可以使用索引访问键值对或者数组。

Object 类型序列化

StandardResolverContractlessStandardResolver可以通过DynamicObjectTypeFallbackResolver将Object类型序列化为具体类型。

var objects = new object[] { 1, "aaa", new ObjectFieldType { Anything = 9999 } };
var bin = MessagePackSerializer.Serialize(objects); // [1,"aaa",[9999]]
Console.WriteLine(MessagePackSerializer.ToJson(bin)); // Support Anonymous Type Serialize
var anonType = new { Foo = 100, Bar = "foobar" };
var bin2 = MessagePackSerializer.Serialize(anonType, MessagePack.Resolvers.ContractlessStandardResolver.Instance); // {"Foo":100,"Bar":"foobar"}
Console.WriteLine(MessagePackSerializer.ToJson(bin2));

Unity支持是有限的。

反序列化时,与Dynamic(Untyped)反序列化相同。

Typeless

Typeless API就像BinaryFormatter, 将类型信息嵌入到二进制中,所以不需要类型去反序列化.

object mc = new Sandbox.MyClass()
{
Age = 10,
FirstName = "hoge",
LastName = "huga"
}; // serialize to typeless
var bin = MessagePackSerializer.Typeless.Serialize(mc); // binary data is embeded type-assembly information.
// ["Sandbox.MyClass, Sandbox",10,"hoge","huga"]
Console.WriteLine(MessagePackSerializer.ToJson(bin)); // can deserialize to MyClass with typeless
var objModel = MessagePackSerializer.Typeless.Deserialize(bin) as MyClass;

类型信息由mspgack ext格式序列化,typecode为100。

MessagePackSerializer.TypelessSerialize / Deserialize <object>(TypelessContractlessStandardResolver.Instance)的快捷方式。 如果要配置默认的Typeless解析器,可以通过MessagePackSerializer.Typeless.RegisterDefaultResolver进行设置。

性能

与其他序列化器在Windows 10 Pro x64 Intel Core i7-6700K 4.00GHz, 32GB RAM上进行Benchmarks比较,Benchmark代码在这-版本信息,ZeroFormatter和FlatBuffers具有非常快速的反序列化器,因此忽略反序列化的性能。

MessagePack for C#使用许多技术来提高性能。

  • 序列化只使用ref byte []和int offset,不使用(Memory)Stream(调用Stream api会有开销)
  • 高级API使用内部内存池,分配工作内存不要低于64k
  • 不创建中间实用程序实例(XxxWriter / Reader,XxxContext等)
  • 所有代码避免装箱,所有平台(包括Unity / IL2CPP)
  • 对静态泛型字段生成的格式化程序进行缓存,查找时从缓存查找(不使用字典缓存,因为字典查找需要一定开销)
  • 重新调整的动态代码生成
  • 当代码生成知道目标是primitive时直接调用PrimitiveAPI
  • 当代码生成知道目标(整数/字符串)范围时,减少可变长度格式的分支
  • 不在迭代集合上使用IEnumerable<T> 抽象
  • 使用预先生成的查找表来减少检查消息包类型所耗时间
  • 对非泛型方法使用优化类型key字典
  • 避免查找映射(字符串键)键的字符串键解码,并使用自动化名称查找与il内联代码生成
  • 对于字符串键编码,预先生成的成员名字节并在IL中使用固定大小的二进制副本

在创建这个库之前,作则实现了一个具有ZeroFormatter#Performance的快速序列化器。 这是一个进一步演变的实现。 MessagePack for C#始终是快速的,为所有类型(原始,小结构,大对象,任何集合)进行了优化。

反序列化中每个方法的性能

性能取决于选项。 这是一个BenchmarkDotNet的微型benchamark。 目标对象有9个成员(MyProperty1〜MyProperty9),值为零。

Method Mean Error Scaled Gen 0 Allocated
IntKey 72.67 ns NA 1.00 0.0132 56 B
StringKey 217.95 ns NA 3.00 0.0131 56 B
Typeless_IntKey 176.71 ns NA 2.43 0.0131 56 B
Typeless_StringKey 378.64 ns NA 5.21 0.0129 56 B
MsgPackCliMap 1,355.26 ns NA 18.65 0.1431 608 B
MsgPackCliArray 455.28 ns NA 6.26 0.0415 176 B
ProtobufNet 265.85 ns NA 3.66 0.0319 136 B
Hyperion 366.47 ns NA 5.04 0.0949 400 B
JsonNetString 2,783.39 ns NA 38.30 0.6790 2864 B
JsonNetStreamReader 3,297.90 ns NA 45.38 1.4267 6000 B
JilString 553.65 ns NA 7.62 0.0362 152 B
JilStreamReader 1,408.46 ns NA 19.38 0.8450 3552 B

IntKey,StringKey,Typeless_IntKey,Typeless_StringKey都是MessagePack for C#的方法

,在反序列化过程中实现零内存分配。JsonNetString /JilString从字符串反序列化。JsonStStreamReader / JilStreamReader是从StreamReader的UTF8 byte []中反序列化的。反序列化通常从Stream读取。 因此,它将从字节数组(或流)而不是字符串中读取。

MessagePack for C#IntKey是最快的。 StringKey比IntKey慢,因为StringKey需要从字符串进行匹配。 如果是IntKey,读取数组长度,根据数组长度进行for循环二进制解码。 如果StringKey,读取map 长度,根据map长度循环,首先需要对密钥解码,然后按照key查找,最后二进制解码,则需要额外两个步骤(解码密钥和按键查找)。

字符串键通常是有用的,无约束的,简单的JSON替换,与其他语言的互操作性,以及更多的某些版本。 MessagePack for C#也为String Key进行了优化。 首先,它不会将UTF8字节数组解码为与成员名称匹配的字符串,它会按原样查找字节数组(避免解码成本和额外分配)。

它会尝试匹配每个长整型(long)(每8个字符,如果长度不够,填充0)使用automata和在生成时内联IL代码。

这也避免了计算字节数组的哈希码,并且可以在长单元上进行多次比较。

这是ILSpy生成的反序列化器代码的示例的反编译。

https://github.com/neuecc/MessagePack-CSharp#performance

如果节点数量很大,则使用嵌入式二进制搜索进行搜索。

另外请注意,这是序列化的基准测试结果。

Method Mean Error Scaled Gen 0 Allocated
IntKey 84.11 ns NA 1.00 0.0094 40 B
StringKey 126.75 ns NA 1.51 0.0341 144 B
Typeless_IntKey 183.31 ns NA 2.18 0.0265 112 B
Typeless_StringKey 193.95 ns NA 2.31 0.0513 216 B
MsgPackCliMap 967.68 ns NA 11.51 0.1297 552 B
MsgPackCliArray 284.20 ns NA 3.38 0.1006 424 B
ProtobufNet 176.43 ns NA 2.10 0.0665 280 B
Hyperion 280.14 ns NA 3.33 0.1674 704 B
ZeroFormatter 149.95 ns NA 1.78 0.1009 424 B
JsonNetString 1,432.55 ns NA 17.03 0.4616 1944 B
JsonNetStreamWriter 1,775.72 ns NA 21.11 1.5526 6522 B
JilString 547.51 ns NA 6.51 0.3481 1464 B
JilStreamWriter 778.78 ns NA 9.26 1.4448 6066 B

当然,IntKey是最快的,但StringKey也不错。

LZ4压缩

MessagePack是一个快速和紧凑的格式,但它不是压缩格式。 LZ4是非常快速的压缩算法,使用MessagePack for C#可以实现极快的性能和非常紧凑的二进制大小!

MessagePack for C#具有内置的LZ4支持。 您可以使用LZ4MessagePackSerializer而不是MessagePackSerializer。 内建支持是特殊的,作者已经创建了序列化压缩管道,并专门调整了管道,所以共享工作内存,不分配,不要调整,直到完成。

序列化二进制不是简单地压缩lz4二进制。 序列化二进制是有效的MessagePack二进制使用ext格式和自定义typecode(99)。

var array= Enumerable.Range(1, 100).Select(x => new MyClass { Age = 5, FirstName = "foo", LastName = "bar" }).ToArray();

// call LZ4MessagePackSerializer instead of MessagePackSerializer, api is completely same
var lz4Bytes = LZ4MessagePackSerializer.Serialize(array);
var mc2 = LZ4MessagePackSerializer.Deserialize<MyClass[]>(lz4Bytes); // you can dump lz4 message pack
// [[5,"hoge","huga"],[5,"hoge","huga"],....]
var json = LZ4MessagePackSerializer.ToJson(lz4Bytes);
Console.WriteLine(json); // lz4Bytes is valid MessagePack, it is using ext-format( [TypeCode:99, SourceLength|CompressedBinary] )
// [99,"0gAAA+vf3ABkkwWjZm9vo2JhcgoA////yVBvo2Jhcg=="]
var rawJson = MessagePackSerializer.ToJson(lz4Bytes);
Console.WriteLine(rawJson);

与protobuf,JSON,ZeroFormatter比较

protbuf-net是.NET上最常用的二进制格式化库。 我(作者)喜欢protobuf-net,并尊重那伟大的工作。 但是如果使用protobuf-net作为通用序列化格式,则可能会引起烦人的问题。

[ProtoContract]
public class Parent
{
[ProtoMember(1)]
public int Primitive { get; set; }
[ProtoMember(2)]
public Child Prop { get; set; }
[ProtoMember(3)]
public int[] Array { get; set; }
} [ProtoContract]
public class Child
{
[ProtoMember(1)]
public int Number { get; set; }
} using (var ms = new MemoryStream())
{
// serialize null.
ProtoBuf.Serializer.Serialize<Parent>(ms, null); ms.Position = 0;
var result = ProtoBuf.Serializer.Deserialize<Parent>(ms); Console.WriteLine(result != null); // True, not null. but all property are zero formatted.
Console.WriteLine(result.Primitive); // 0
Console.WriteLine(result.Prop); // null
Console.WriteLine(result.Array); // null
} using (var ms = new MemoryStream())
{
// serialize empty array.
ProtoBuf.Serializer.Serialize<Parent>(ms, new Parent { Array = new int[0] }); ms.Position = 0;
var result = ProtoBuf.Serializer.Deserialize<Parent>(ms); Console.WriteLine(result.Array == null); // True, null!
}

protobuf(-net)不能正确处理null和空集合。 因为protobuf没有null表示(这是protobuf-net作者的答案)。

MessagePack规范可以完全序列化C#类型。 这就是推荐MessagePack而不是protobuf的原因。

Protocol Buffers具有良好的IDL和gRPC,这比MessagePack好得多。 如果你想使用IDL,我(作者)推荐Google.Protobuf。

JSON是很好的通用格式。 这是完美的,简单的,足够规范的。 Utf8Json创建了我采用与MessagePack for C#相同的体系结构,并避免编码/修饰成本,所以像二进制一样工作。 如果你想了解二进制与文本,请参阅Utf8Json /应使用哪个序列化器部分。

ZeroFormatter与FlatBuffers类似,但专门用于C#。 这是特别的。 反序列化速度非常快,但是二进制大小却很大。 而ZeroFormatter的缓存算法需要额外的内存。

ZeroFormatter也是特别的。 当与ZeroFormatter对比的情况下,它显示格式化的力量。 但是对于许多常见的用途,MessagePack for C#会更好。

扩展

MessagePack for C#具有扩展点,您可以添加外部类型的序列化支持。 下列是官方扩展支持。

Install-Package MessagePack.ImmutableCollection
Install-Package MessagePack.ReactiveProperty
Install-Package MessagePack.UnityShims
Install-Package MessagePack.AspNetCoreMvcFormatter

MessagePack.ImmutableCollection 添加对 System.Collections.Immutable 的支持. 添加了对ImmutableArray<>, ImmutableList<>, ImmutableDictionary<,>, ImmutableHashSet<>, ImmutableSortedDictionary<,>, ImmutableSortedSet<>, ImmutableQueue<>, ImmutableStack<>, IImmutableList<>, IImmutableDictionary<,>, IImmutableQueue<>, IImmutableSet<>, IImmutableStack<>的序列化支持.

MessagePack.ReactiveProperty包添加对ReactiveProperty库的支持。它增加了ReactiveProperty <>,IReactiveProperty <>,IReadOnlyReactiveProperty <>,ReactiveCollection <>,unit序列化支持。 这对保存视图模型状态很有用。

MessagePack.AspNetCoreMvcFormatter是ASP.NET Core MVC序列化的附加组件,可提升性能。 这是配置示例。

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddMvcOptions(option =>
{
option.OutputFormatters.Clear();
option.OutputFormatters.Add(new MessagePackOutputFormatter(ContractlessStandardResolver.Instance));
option.InputFormatters.Clear();
option.InputFormatters.Add(new MessagePackInputFormatter(ContractlessStandardResolver.Instance));
});
}

更多信息请访问github: https://github.com/neuecc/MessagePack-CSharp

快速序列化组件MessagePack介绍的更多相关文章

  1. c#的二进制序列化组件MessagePack介绍

    c#的序列化有多种,我一般喜欢用第三方组件,一个公共组件要拿出来用,而且支持很多语言,甚至以此谋生,肯定有其优势. 有或者说存在必然有其合理性,经过几年开发,我更加喜欢第三方的东西,类似序列化的东西. ...

  2. 序列化 反序列化 MessagePack for C#

    阅读目录 快速序列化组件MessagePack介绍 简介 使用 快速开始 分析器 内置的支持类型 对象序列化 DataContract兼容性 序列化不可变对象(序列化构造器) 序列化回调 Union ...

  3. 一种高效的序列化方式——MessagePack

    最近在弄一些数据分析方面的内容,发现很多时候数据瓶颈在模块之间的数据序列化和反序列化上了,原来项目中用的是Json,找了一圈发现Json.net在Json序列化库中已经是性能的佼佼者了,便准备从序列化 ...

  4. rest_framework之ModelViewSet、路由控制、序列化组件快速搭建项目雏形

    以UserInfo表登陆接口为例 ModelViewSet的用法十分简单,定义一个视图类,指定一个模型表,指定一个序列化类即可帮我们完成增删改查等功能 示例: # 视图层 from app01.MyS ...

  5. DRF框架(二)——解析模块(parsers)、异常模块(exception_handler)、响应模块(Response)、三大序列化组件介绍、Serializer组件(序列化与反序列化使用)

    解析模块 为什么要配置解析模块 1)drf给我们提供了多种解析数据包方式的解析类 form-data/urlencoded/json 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些 ...

  6. 第六章、ajax方法以及序列化组件

    目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...

  7. cvb源码分析,resful规范,drf,drf序列化组件,95

    1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...

  8. rest-framework之APIView 序列化组件

    rest-framework之APIView 一 安装djangorestframework 方式一:pip3 install djangorestframework 方式二:pycharm图形化界面 ...

  9. DRF(3) - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ...

随机推荐

  1. HTML知识速递

    1.html的定义 超文本标记语言(Hypertext Markup Language,HTML)通过标签语言来标记要显示的网页中的各个部分.一套规则,浏览器认识的规则 浏览器按顺序渲染网页文件,然后 ...

  2. Jdbc访问数据库篇

    一万年太久,只争朝夕 What JDBC 上部 JDBC(Java DataBase Connectivity)Java 数据库连接,主要提供编写 Java 数据库应用程序的 API 支持 java. ...

  3. python 有关datetime时间日期 以及时间戳转换

    直接上代码 其中有注释 #coding=utf-8 import time import datetime def yes_time(): #获取当前时间 now_time = datetime.da ...

  4. JavaScript基本知识点整理(超实用)

      絮叨絮叨                   今天给大家分享一下这两天自己整理的JavaScript部分的笔记,下面都是我觉得比较常用的,希望能帮助到大家! 1. 导入JS的三种方式 ①在HTML ...

  5. 初学者没有搞明白的GOROOT,GOPATH,GOBIN,project目录

    我们接下来一个一个来看关于Go语言中的三个目录的详细解释先通过go env查看go的环境变量(我这里是mac的环境,所以可能和你的不同) localhost:~ zhaofan$ go env GOA ...

  6. Docker技术浅谈:私有化部署的优势以及在顶象内部的应用实践

    顶象全景式业务安全风控体系基于新一代风控体系构建,并采用Docker技术进行私有云和公有云部署.本文主要和大家分享下Docker容器技术和顶象风控系统私有化部署的优势以及Docker容器技术在顶象内部 ...

  7. 多服务器操作利器 - Polysh

    多台服务器下的痛苦人生 分布式架构下的系统,可以说每个服务都是分别部署在多台服务器上的,有的甚至还需要多机房,在这种架构下可以说可以很好的做到了易扩展.容灾等功能.推荐的服务部署为一服务多机器.一机器 ...

  8. Servlet之过滤器(Filter)和监听器(Listener)

    过滤器 过滤器是一个java组件,可以拦截发送至某个servelet,jsp页面或静态页面的请求,可以在响应发送到客户之前进行拦截 工作原理: 过滤器类必须实现 Filter 接口,包含的方法如下: ...

  9. Docker 使用教程

    概括  Docker与传统虚拟机的区别 与传统虚拟机的区别  Docker的安装 的安装  Docker daemon , client , containerd  镜像与容器操作  容器运 ...

  10. SPFA【模板】单源最短路径

    题目传送 https://www.luogu.org/problem/show?pid=3371没啥解释,SPFA纯模版qaq//Gang #include<iostream> #incl ...