Skip to content

trs4/IcyRain

Repository files navigation

IcyRain

Fastest C# data serializer and deserializer for .NET Core, .NET Framework for use in Grpc.Core C# library with SerializationContext base on IBufferWriter and DeserializationContext base on ReadOnlySequence (see example). And also supports serialization via byte[] or ArraySegment. See performance

Principle - performance first.

Install

Package -> IcyRain

Nuget

Quick start

1 Use the contract definition as in WCF with mark [DataContract] on classes and [DataMember(Order = PropertyNumber)] on properties with required parameter Order. Order value must be unique on the properties of the class.

[DataContract]
public class TestData
{
    [DataMember(Order = 1)]
    public bool Property1 { get; set; }

    [DataMember(Order = 2)]
    public int Property2 { get; set; }

    [DataMember(Order = 3)]
    public double Property3 { get; set; }

    [DataMember(Order = 4)]
    public DateTime Property4 { get; set; }

    [DataMember(Order = 5)]
    public string Property5 { get; set; }
}
  • Inherited classes must be marked with attributes [KnownType(typeof(TestData2))] in the base class.

2 Serialize / Deserialize data

var data = new TestData
{
    Property1 = true,
    Property2 = 25,
    Property3 = 7.0,
    Property4 = DateTime.Now,
    Property5 = "test"
};

// byte array serialization
byte[] bytes = Serialization.Serialize(data);
TestData bytesClone = Serialization.Deserialize<TestData>(bytes);

// array segment serialization
ArraySegment<byte> segment = Serialization.SerializeSegment(data);
TestData segmentClone = Serialization.DeserializeSegment<TestData>(segment);

// IBufferWriter<byte> & ReadOnlySequence<byte> serialization
IBufferWriter<byte> buffer = ...;
Serialization.Serialize(buffer, data);
ReadOnlySequence<byte> sequence = ...;
TestData sequenceClone = Serialization.Deserialize<TestData>(sequence);

DateTime

DateTime are serialized in UTC format with time zone and deserialized with time zone. In order to deserialize a DateTime in a particular time zone need use DeserializeOptions

T Deserialize<T>(in ReadOnlySequence<byte> sequence, DeserializeOptions options = null)
public sealed class DeserializeOptions
{
    public DeserializeOptions(DateTimeKind dateTimeZone)
        => DateTimeZone = dateTimeZone;

    public DateTimeKind DateTimeZone { get; }
}

Performance

Deep clone = serialize + deserialize

Serialization use IBufferWriter and ReadOnlySequence

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.14393.4169 (1607/AnniversaryUpdate/Redstone1) Intel Core i7-4770K CPU 3.50GHz (Haswell), 1 CPU, 8 logical and 4 physical cores Frequency=3415997 Hz, Resolution=292.7403 ns, Timer=TSC [Host] : .NET Framework 4.8 (4.8.4311.0), X64 RyuJIT Job-SKJJXH : .NET Core 5.0.2 (CoreCLR 5.0.220.61120, CoreFX 5.0.220.61120), X64 RyuJIT

Runtime=.NET Core 5.0 Toolchain=netcoreapp50

  • Int:
|          Method | Categories |        Mean |    Error |   StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------- |----------- |------------:|---------:|---------:|-------:|------:|------:|----------:|
|         IcyRain |  Serialize |    18.41 ns | 0.286 ns | 0.477 ns | 0.0076 |     - |     - |      32 B |
|   ZeroFormatter |  Serialize |    38.08 ns | 0.151 ns | 0.142 ns | 0.0153 |     - |     - |      64 B |
|    protobuf-net |  Serialize |   132.05 ns | 0.479 ns | 0.374 ns | 0.0362 |     - |     - |     152 B |
| Google.Protobuf |  Serialize |   858.70 ns | 4.957 ns | 4.636 ns | 1.9455 |     - |     - |    8152 B |
|     MessagePack |  Serialize |   901.08 ns | 3.875 ns | 3.435 ns | 1.9379 |     - |     - |    8120 B |
|                 |            |             |          |          |        |       |       |           |
|         IcyRain | Deep clone |    50.81 ns | 0.896 ns | 0.838 ns | 0.0153 |     - |     - |      64 B |
|   ZeroFormatter | Deep clone |    56.62 ns | 0.152 ns | 0.142 ns | 0.0153 |     - |     - |      64 B |
|    protobuf-net | Deep clone |   359.64 ns | 2.009 ns | 1.781 ns | 0.0362 |     - |     - |     152 B |
| Google.Protobuf | Deep clone |   940.40 ns | 6.941 ns | 5.796 ns | 1.9569 |     - |     - |    8184 B |
|     MessagePack | Deep clone | 1,034.78 ns | 5.574 ns | 5.214 ns | 1.9379 |     - |     - |    8120 B |
  • List of int:
|        Method | Categories |        Mean |     Error |    StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |------------:|----------:|----------:|-------:|------:|------:|----------:|
|       IcyRain |  Serialize |    461.2 ns |   2.64 ns |   2.20 ns | 0.9708 |     - |     - |   3.97 KB |
| ZeroFormatter |  Serialize |  6,008.9 ns |  60.85 ns |  53.94 ns | 1.9302 |     - |     - |   7.91 KB |
|   MessagePack |  Serialize | 10,425.3 ns | 108.92 ns | 101.88 ns | 1.9684 |     - |     - |   8.05 KB |
|  protobuf-net |  Serialize | 27,303.2 ns | 256.27 ns | 239.72 ns | 1.3733 |     - |     - |   5.67 KB |
|               |            |             |           |           |        |       |       |           |
|       IcyRain | Deep clone |  2,048.2 ns |  30.79 ns |  28.80 ns | 3.8872 |     - |     - |  15.89 KB |
| ZeroFormatter | Deep clone | 11,086.4 ns |  84.81 ns |  79.33 ns | 2.8992 |     - |     - |  11.87 KB |
|  protobuf-net | Deep clone | 28,310.6 ns | 145.89 ns | 121.82 ns | 1.4038 |     - |     - |   5.78 KB |
|   MessagePack | Deep clone | 29,403.0 ns | 158.36 ns | 140.38 ns | 2.9297 |     - |     - |  12.02 KB |
  • List of string:
|        Method | Categories |      Mean |     Error |    StdDev |   Gen 0 |  Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |----------:|----------:|----------:|--------:|-------:|------:|----------:|
|       IcyRain |  Serialize |  5.275 μs | 0.0935 μs | 0.0874 μs |  3.5706 |      - |     - |   14952 B |
|   MessagePack |  Serialize | 18.517 μs | 0.3334 μs | 0.5384 μs |  2.7161 |      - |     - |   11416 B |
| ZeroFormatter |  Serialize | 25.112 μs | 0.3311 μs | 0.3097 μs | 12.8174 |      - |     - |   53640 B |
|  protobuf-net |  Serialize | 47.067 μs | 0.4627 μs | 0.4102 μs |  2.9907 |      - |     - |   12648 B |
|               |            |           |           |           |         |        |       |           |
|       IcyRain | Deep clone | 22.053 μs | 0.4278 μs | 0.6270 μs | 17.7002 | 1.7700 |     - |   74304 B |
|  protobuf-net | Deep clone | 50.857 μs | 0.9976 μs | 1.8980 μs |  3.0518 |      - |     - |   12864 B |
| ZeroFormatter | Deep clone | 51.441 μs | 0.4688 μs | 0.3915 μs | 19.5313 |      - |     - |   81744 B |
|   MessagePack | Deep clone |        NA |        NA |        NA |       - |      - |     - |         - |
  • List of DateTime:
|        Method | Categories |      Mean |     Error |    StdDev |    Median |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |----------:|----------:|----------:|----------:|-------:|------:|------:|----------:|
|       IcyRain |  Serialize |  3.437 μs | 0.0117 μs | 0.0104 μs |  3.438 μs | 1.5640 |     - |     - |    6560 B |
| ZeroFormatter |  Serialize |  6.503 μs | 0.0345 μs | 0.0306 μs |  6.507 μs | 2.8839 |     - |     - |   12096 B |
|   MessagePack |  Serialize |  7.279 μs | 0.0153 μs | 0.0143 μs |  7.280 μs | 1.9684 |     - |     - |    8248 B |
|  protobuf-net |  Serialize | 83.675 μs | 1.6433 μs | 2.9632 μs | 81.573 μs | 1.4648 |     - |     - |    6416 B |
|               |            |           |           |           |           |        |       |       |           |
|       IcyRain | Deep clone |  8.117 μs | 0.0343 μs | 0.0321 μs |  8.110 μs | 5.0964 |     - |     - |   21360 B |
| ZeroFormatter | Deep clone | 15.392 μs | 0.0495 μs | 0.0413 μs | 15.374 μs | 3.8452 |     - |     - |   16152 B |
|   MessagePack | Deep clone | 21.686 μs | 0.0701 μs | 0.0621 μs | 21.673 μs | 2.9297 |     - |     - |   12304 B |
|  protobuf-net | Deep clone |        NA |        NA |        NA |        NA |      - |     - |     - |         - |
  • List of Double:
|        Method | Categories |        Mean |     Error |    StdDev |      Median |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |------------:|----------:|----------:|------------:|-------:|------:|------:|----------:|
|       IcyRain |  Serialize |    467.7 ns |   3.92 ns |   3.47 ns |    467.1 ns | 0.9708 |     - |     - |   3.97 KB |
| ZeroFormatter |  Serialize |  5,482.3 ns |  27.28 ns |  24.18 ns |  5,481.5 ns | 1.9302 |     - |     - |   7.91 KB |
|   MessagePack |  Serialize |  5,767.1 ns | 109.46 ns | 126.05 ns |  5,723.5 ns | 1.9684 |     - |     - |   8.05 KB |
|  protobuf-net |  Serialize | 10,966.8 ns |  98.73 ns |  92.35 ns | 10,929.8 ns | 1.3123 |     - |     - |   5.38 KB |
|               |            |             |           |           |             |        |       |       |           |
|       IcyRain | Deep clone |  2,089.6 ns |  32.40 ns |  27.05 ns |  2,077.7 ns | 3.8872 |     - |     - |  15.89 KB |
| ZeroFormatter | Deep clone | 10,768.0 ns |  43.22 ns |  36.09 ns | 10,760.1 ns | 2.8992 |     - |     - |  11.87 KB |
|  protobuf-net | Deep clone | 12,049.9 ns | 213.28 ns | 291.94 ns | 11,890.3 ns | 1.3428 |     - |     - |   5.54 KB |
|   MessagePack | Deep clone | 12,960.6 ns |  47.61 ns |  42.21 ns | 12,955.8 ns | 2.9297 |     - |     - |  12.02 KB |
  • Class with DataContract:
on net5.0:
|        Method |        Job |       Runtime |    Toolchain | Categories |       Mean |    Error |  StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |-------------- |------------- |----------- |-----------:|---------:|--------:|------:|--------:|-------:|------:|------:|----------:|
|       IcyRain | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize |   157.7 ns |  0.49 ns | 0.46 ns |  0.73 |    0.00 | 0.0248 |     - |     - |     104 B |
|  protobuf-net | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize |   432.0 ns |  1.60 ns | 1.50 ns |  0.76 |    0.00 | 0.0439 |     - |     - |     184 B |
|   MessagePack | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize |   866.7 ns |  2.53 ns | 2.11 ns |  0.84 |    0.01 | 1.9684 |     - |     - |    8248 B |
|       IcyRain | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone |   383.6 ns |  1.23 ns | 1.09 ns |  0.67 |    0.00 | 0.0744 |     - |     - |     312 B |
|  protobuf-net | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone |   944.4 ns |  3.41 ns | 3.02 ns |  0.65 |    0.00 | 0.0629 |     - |     - |     264 B |
|   MessagePack | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone | 1,166.0 ns |  4.41 ns | 3.68 ns |  0.73 |    0.00 | 1.9875 |     - |     - |    8328 B |

on net472:
|        Method | Categories |       Mean |    Error |   StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |-----------:|---------:|---------:|-------:|------:|------:|----------:|
|       IcyRain |  Serialize |   207.5 ns |  3.31 ns |  3.68 ns | 0.0248 |     - |     - |     104 B |
| ZeroFormatter |  Serialize |   312.4 ns |  4.75 ns |  4.45 ns | 0.1259 |     - |     - |     530 B |
|  protobuf-net |  Serialize |   551.2 ns |  4.06 ns |  3.60 ns | 0.0439 |     - |     - |     185 B |
|   MessagePack |  Serialize |   992.8 ns | 13.87 ns | 11.58 ns | 1.9684 |     - |     - |    8272 B |
|               |            |            |          |          |        |       |       |           |
|       IcyRain | Deep clone |   545.8 ns |  7.29 ns |  6.82 ns | 0.0839 |     - |     - |     353 B |
| ZeroFormatter | Deep clone |   691.6 ns |  7.17 ns |  6.71 ns | 0.2003 |     - |     - |     842 B |
|   MessagePack | Deep clone | 1,559.8 ns | 15.50 ns | 13.74 ns | 1.9913 |     - |     - |    8371 B |
|  protobuf-net | Deep clone | 1,593.7 ns | 31.19 ns | 34.67 ns | 0.0648 |     - |     - |     273 B |
  • HashSet of int:
|        Method | Categories |      Mean |     Error |    StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |----------:|----------:|----------:|-------:|------:|------:|----------:|
|       IcyRain |  Serialize |  1.013 μs | 0.0164 μs | 0.0154 μs | 0.2060 |     - |     - |     864 B |
| ZeroFormatter |  Serialize |  2.459 μs | 0.0468 μs | 0.0592 μs | 0.4120 |     - |     - |    1736 B |
|   MessagePack |  Serialize |  3.493 μs | 0.0157 μs | 0.0139 μs | 1.9684 |     - |     - |    8248 B |
|  protobuf-net |  Serialize |  5.892 μs | 0.0267 μs | 0.0236 μs | 0.2670 |     - |     - |    1136 B |
|               |            |           |           |           |        |       |       |           |
|       IcyRain | Deep clone |  4.373 μs | 0.0174 μs | 0.0145 μs | 1.5945 |     - |     - |    6696 B |
|  protobuf-net | Deep clone |  6.502 μs | 0.0200 μs | 0.0177 μs | 0.3128 |     - |     - |    1312 B |
| ZeroFormatter | Deep clone |  7.430 μs | 0.0530 μs | 0.0470 μs | 3.5095 |     - |     - |   14697 B |
|   MessagePack | Deep clone | 12.236 μs | 0.0399 μs | 0.0354 μs | 5.0659 |     - |     - |   21208 B |
  • Dictionary with int key and string value:
|        Method |        Job |       Runtime |    Toolchain | Categories |      Mean |     Error |    StdDev | Ratio | RatioSD |   Gen 0 |  Gen 1 | Gen 2 | Allocated |
|-------------- |----------- |-------------- |------------- |----------- |----------:|----------:|----------:|------:|--------:|--------:|-------:|------:|----------:|
|  protobuf-net | Job-LBIENB |    .NET 4.7.2 |       net472 | Deep clone |        NA |        NA |        NA |     ? |       ? |       - |      - |     - |         - |
|  protobuf-net | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone | 57.991 μs | 1.1252 μs | 1.5773 μs |     ? |       ? |  1.0376 |      - |     - |    4584 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
|       IcyRain | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize |  4.781 μs | 0.0867 μs | 0.1216 μs |  0.66 |    0.02 |  1.2360 |      - |     - |    5200 B |
|       IcyRain | Job-LBIENB |    .NET 4.7.2 |       net472 |  Serialize |  7.353 μs | 0.0509 μs | 0.0397 μs |  1.00 |    0.00 |  1.2436 |      - |     - |    5243 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
|       IcyRain | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone | 18.962 μs | 0.3733 μs | 0.6539 μs |  0.74 |    0.03 |  7.9956 | 0.5188 |     - |   33456 B |
|       IcyRain | Job-LBIENB |    .NET 4.7.2 |       net472 | Deep clone | 25.558 μs | 0.1681 μs | 0.1572 μs |  1.00 |    0.00 | 10.6201 |      - |     - |   44574 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
| ZeroFormatter | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize | 13.338 μs | 0.2632 μs | 0.4251 μs |  0.74 |    0.03 |  3.5706 |      - |     - |   14936 B |
| ZeroFormatter | Job-LBIENB |    .NET 4.7.2 |       net472 |  Serialize | 18.476 μs | 0.3302 μs | 0.2927 μs |  1.00 |    0.00 |  3.5706 |      - |     - |   14983 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
| ZeroFormatter | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone | 28.635 μs | 0.1558 μs | 0.1381 μs |  0.69 |    0.01 |  7.1106 |      - |     - |   29808 B |
| ZeroFormatter | Job-LBIENB |    .NET 4.7.2 |       net472 | Deep clone | 41.562 μs | 0.5594 μs | 0.5233 μs |  1.00 |    0.00 |  7.4463 |      - |     - |   31509 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
|   MessagePack | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize |  9.861 μs | 0.0561 μs | 0.0438 μs |  0.49 |    0.00 |  1.9684 |      - |     - |    8248 B |
|   MessagePack | Job-LBIENB |    .NET 4.7.2 |       net472 |  Serialize | 19.951 μs | 0.0919 μs | 0.0718 μs |  1.00 |    0.00 |  1.9531 |      - |     - |    8272 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
|   MessagePack | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 | Deep clone | 26.304 μs | 0.2359 μs | 0.2092 μs |  0.50 |    0.01 |  5.4932 | 0.0305 |     - |   23072 B |
|   MessagePack | Job-LBIENB |    .NET 4.7.2 |       net472 | Deep clone | 52.847 μs | 0.3498 μs | 0.3101 μs |  1.00 |    0.00 |  5.8594 |      - |     - |   24752 B |
|               |            |               |              |            |           |           |           |       |         |         |        |       |           |
|  protobuf-net | Job-SKJJXH | .NET Core 5.0 | netcoreapp50 |  Serialize | 56.799 μs | 0.3132 μs | 0.2777 μs |  0.71 |    0.01 |  0.9766 |      - |     - |    4328 B |
|  protobuf-net | Job-LBIENB |    .NET 4.7.2 |       net472 |  Serialize | 79.973 μs | 0.6766 μs | 0.6329 μs |  1.00 |    0.00 |  0.9766 |      - |     - |    4189 B |
  • Bool:
|          Method | Categories |        Mean |     Error |    StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------- |----------- |------------:|----------:|----------:|-------:|------:|------:|----------:|
|         IcyRain |  Serialize |    19.54 ns |  0.106 ns |  0.094 ns | 0.0076 |     - |     - |      32 B |
|   ZeroFormatter |  Serialize |    37.42 ns |  0.202 ns |  0.189 ns | 0.0153 |     - |     - |      64 B |
|    protobuf-net |  Serialize |   136.33 ns |  2.436 ns |  3.080 ns | 0.0362 |     - |     - |     152 B |
| Google.Protobuf |  Serialize |   889.98 ns | 10.456 ns |  9.780 ns | 1.9455 |     - |     - |    8152 B |
|     MessagePack |  Serialize |   945.22 ns | 17.413 ns | 16.288 ns | 1.9379 |     - |     - |    8120 B |
|                 |            |             |           |           |        |       |       |           |
|         IcyRain | Deep clone |    40.86 ns |  0.363 ns |  0.303 ns | 0.0153 |     - |     - |      64 B |
|   ZeroFormatter | Deep clone |    55.53 ns |  0.680 ns |  0.568 ns | 0.0153 |     - |     - |      64 B |
|    protobuf-net | Deep clone |   361.86 ns |  4.269 ns |  3.784 ns | 0.0362 |     - |     - |     152 B |
| Google.Protobuf | Deep clone |   987.89 ns | 15.617 ns | 21.893 ns | 1.9569 |     - |     - |    8184 B |
|     MessagePack | Deep clone | 1,035.23 ns |  9.534 ns |  7.961 ns | 1.9379 |     - |     - |    8120 B |
  • Byte array:
|          Method | Categories |       Mean |    Error |   StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------- |----------- |-----------:|---------:|---------:|-------:|------:|------:|----------:|
|         IcyRain |  Serialize |   138.9 ns |  0.87 ns |  0.81 ns | 0.2580 |     - |     - |    1080 B |
|   ZeroFormatter |  Serialize |   296.0 ns |  2.74 ns |  2.56 ns | 0.5121 |     - |     - |    2144 B |
|    protobuf-net |  Serialize |   566.7 ns | 11.37 ns | 17.36 ns | 0.3347 |     - |     - |    1400 B |
|     MessagePack |  Serialize | 1,024.9 ns |  8.44 ns |  7.48 ns | 1.9684 |     - |     - |    8248 B |
| Google.Protobuf |  Serialize | 1,090.5 ns | 12.45 ns | 11.04 ns | 2.2106 |     - |     - |    9256 B |
|                 |            |            |          |          |        |       |       |           |
|    protobuf-net | Deep clone |         NA |       NA |       NA |      - |     - |     - |         - |
|         IcyRain | Deep clone |   145.3 ns |  2.06 ns |  1.93 ns | 0.2580 |     - |     - |    1080 B |
|   ZeroFormatter | Deep clone |   459.3 ns |  5.77 ns |  5.40 ns | 0.7629 |     - |     - |    3192 B |
| Google.Protobuf | Deep clone | 1,329.6 ns | 10.73 ns | 10.03 ns | 2.4738 |     - |     - |   10360 B |
|     MessagePack | Deep clone | 1,372.9 ns |  8.93 ns |  7.91 ns | 2.2221 |     - |     - |    9296 B |