.NET对象序列化和反序列化的最快方法

97

我正在寻找最快的方法来序列化和反序列化 .NET 对象。这是我目前所拥有的:

public class TD
{
    public List<CT> CTs { get; set; }
    public List<TE> TEs { get; set; }
    public string Code { get; set; }
    public string Message { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }

    public static string Serialize(List<TD> tData)
    {
        var serializer = new XmlSerializer(typeof(List<TD>));

        TextWriter writer = new StringWriter();
        serializer.Serialize(writer, tData);

        return writer.ToString();
    }

    public static List<TD> Deserialize(string tData)
    {
        var serializer = new XmlSerializer(typeof(List<TD>));

        TextReader reader = new StringReader(tData);

        return (List<TD>)serializer.Deserialize(reader);
    }        
}

2
性能还是代码占用空间? - ulrichb
你是在问我需要性能数据还是代码? - aron
3
他在询问你所说的“最快的方式”是指性能还是代码占用空间。 BinaryFormatter 在代码和实现方面非常快,但像Marc的解决方案这样的解决方案在基准测试中的表现会更快。 - Cody Gray
好的,我明白了。我的意思是在性能方面… - aron
有很多链接可以找到。其中之一是:http://blogs.msdn.com/b/youssefm/archive/2009/07/10/comparing-the-performance-of-net-serializers.aspx - nawfal
“速度”是一个方面,产生的“大小”是另一个方面,“安全性”是第三个方面。 安全序列化程序通常是非多态的,可能需要注释合同。 但是,如果有效负载是从网络流、文件或数据库中检索的,则序列化本身的速度无关紧要。 我不会复制并粘贴我早些时候的答案,因此请参见链接以获取有关二进制(和任何多态)序列化程序的更多想法。 - György Kőszeg
9个回答

61

这是您的模型(使用虚构的CTTE)使用protobuf-net进行序列化(仍然保留使用XmlSerializer的功能,这可能很有用-特别是用于迁移); 如果需要证据,我谦卑地提交,这个 .NET 中最快的(或者至少是最快之一)通用序列化器。

如果您需要字符串,只需对二进制进行Base64编码即可。

[XmlType]
public class CT {
    [XmlElement(Order = 1)]
    public int Foo { get; set; }
}
[XmlType]
public class TE {
    [XmlElement(Order = 1)]
    public int Bar { get; set; }
}
[XmlType]
public class TD {
    [XmlElement(Order=1)]
    public List<CT> CTs { get; set; }
    [XmlElement(Order=2)]
    public List<TE> TEs { get; set; }
    [XmlElement(Order = 3)]
    public string Code { get; set; }
    [XmlElement(Order = 4)]
    public string Message { get; set; }
    [XmlElement(Order = 5)]
    public DateTime StartDate { get; set; }
    [XmlElement(Order = 6)]
    public DateTime EndDate { get; set; }

    public static byte[] Serialize(List<TD> tData) {
        using (var ms = new MemoryStream()) {
            ProtoBuf.Serializer.Serialize(ms, tData);
            return ms.ToArray();
        }            
    }

    public static List<TD> Deserialize(byte[] tData) {
        using (var ms = new MemoryStream(tData)) {
            return ProtoBuf.Serializer.Deserialize<List<TD>>(ms);
        }
    }
}

2
嗨,马克,我很喜欢你所做的协议缓冲工作。虽然这篇文章已经有近5年的历史了,但是在这里(Binoj)引用的netserializer指标表明你的实现并不是最快的。这是一个公正的陈述/广告吗?还是存在某种权衡?谢谢。 - Jeremy Thompson
1
任何认为这很快的人一定在吸毒,它可能对许多情况来说足够快,而且可能比其他许多串行化更快,但与手动解析相比,它真的快吗?天哪,不是的。 - BjarkeCK
3
@BjarkeCK 序列化器本质上比较复杂,因为它们需要做很多事情来防止人们自己搞砸(特别是当它们迭代版本时);大多数人不想花费他们的生命来调试序列化代码,所以:一个好的序列化器 - 虽然无疑比完美实现的版本不兼容的手动实现要慢 - 通常对大多数人来说是一个很好的折衷方案。 - Marc Gravell
1
@MarcGravell 绝对没错,只是希望这里至少有一个人能回复一个真正快速的方法。我们应该更加关注简单的东西,教育人们编写好的简单代码,少用抽象,而不是“去使用这个库”——顺便说一句,通常会在很多其他方面浪费你的时间...很多时候,你最好自己编写一些东西,而且通常比人们想象的要容易得多,你的软件也通常会更快,你将拥有更多的可能性,因为你有控制权。 - BjarkeCK
7
我非常不同意;对于大多数人来说,这甚至不是完全有用的。接下来呢,每天编写我们自己的集合吗?不,要做好这些东西是非常困难的。当然,如果你确实需要最快的输出:你必须亲自动手——但对于大多数人来说,这样做将是一种非常浪费时间的劣质选择。最好的情况就是花费更长的时间来完成。更可能的是,他们的代码会有缺陷、不可靠,并且可能比使用可用库更慢。大多数人应该专注于他们的应用程序需要什么,而不是这些细节问题。 - Marc Gravell
显示剩余4条评论

36

13
那不是速度,那是慢。链接的文章中写着“越小越好”。 - Timur Nuriyasov
2
@TimurNuriyasov,这就是完成操作所花费的时间。 - Maxim
2
那么你说二进制是最慢的?我不这么认为!我猜它正确地指的是速度,而不是时间。 - Javid
3
二进制是最慢的。你可以自己试试。但我认为它最容易,因为它不需要任何自定义解析工具来正确处理多态对象(接口等)。 - Kamarey
2
@Kamarey 看一下我下面的测试…二进制比其他的都要快得多。 - Jeremy Holovacs

27

由于我对此很感兴趣,我决定用最接近“苹果到苹果”的测试来测试建议的方法。我编写了一个控制台应用程序,并使用以下代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace SerializationTests
{
    class Program
    {
        static void Main(string[] args)
        {
            var count = 100000;
            var rnd = new Random(DateTime.UtcNow.GetHashCode());
            Console.WriteLine("Generating {0} arrays of data...", count);
            var arrays = new List<int[]>();
            for (int i = 0; i < count; i++)
            {
                var elements = rnd.Next(1, 100);
                var array = new int[elements];
                for (int j = 0; j < elements; j++)
                {
                    array[j] = rnd.Next();
                }   
                arrays.Add(array);
            }
            Console.WriteLine("Test data generated.");
            var stopWatch = new Stopwatch();

            Console.WriteLine("Testing BinarySerializer...");
            var binarySerializer = new BinarySerializer();
            var binarySerialized = new List<byte[]>();
            var binaryDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                binarySerialized.Add(binarySerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in binarySerialized)
            {
                binaryDeserialized.Add(binarySerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);


            Console.WriteLine();
            Console.WriteLine("Testing ProtoBuf serializer...");
            var protobufSerializer = new ProtoBufSerializer();
            var protobufSerialized = new List<byte[]>();
            var protobufDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                protobufSerialized.Add(protobufSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in protobufSerialized)
            {
                protobufDeserialized.Add(protobufSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Testing NetSerializer serializer...");
            var netSerializerSerializer = new ProtoBufSerializer();
            var netSerializerSerialized = new List<byte[]>();
            var netSerializerDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                netSerializerSerialized.Add(netSerializerSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in netSerializerSerialized)
            {
                netSerializerDeserialized.Add(netSerializerSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine("Press any key to end.");
            Console.ReadKey();
        }

        public class BinarySerializer
        {
            private static readonly BinaryFormatter Formatter = new BinaryFormatter();

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Formatter.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = (T)Formatter.Deserialize(stream);
                    return result;
                }
            }
        }

        public class ProtoBufSerializer
        {
            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    ProtoBuf.Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = ProtoBuf.Serializer.Deserialize<T>(stream);
                    return result;
                }
            }
        }

        public class NetSerializer
        {
            private static readonly NetSerializer Serializer = new NetSerializer();
            public byte[] Serialize(object toSerialize)
            {
                return Serializer.Serialize(toSerialize);
            }

            public T Deserialize<T>(byte[] serialized)
            {
                return Serializer.Deserialize<T>(serialized);
            }
        }
    }
}

结果让我感到惊讶,多次运行时它们是一致的:
Generating 100000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 336.8392ms.
BinaryFormatter: Deserializing took 208.7527ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 2284.3827ms.
ProtoBuf: Deserializing took 2201.8072ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 2139.5424ms.
NetSerializer: Deserializing took 2113.7296ms.
Press any key to end.

收集这些结果后,我决定测试ProtoBuf或NetSerializer在处理更大对象时的表现。我将集合计数更改为10,000个对象,但将数组的大小增加到1-10,000而不是1-100。结果似乎更加明确:

Generating 10000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 285.8356ms.
BinaryFormatter: Deserializing took 206.0906ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 10693.3848ms.
ProtoBuf: Deserializing took 5988.5993ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 9017.5785ms.
NetSerializer: Deserializing took 5978.7203ms.
Press any key to end.

因此,我的结论是:对于相对简单的对象而言,在性能方面 BinaryFormatter 明显比 ProtoBuf 和 NetSerializer 更具性价比,但也可能存在适用 ProtoBuf 和 NetSerializer 的情况。

个人体验可能有所不同。

1
也许 BinaryFormatter 处理数组的速度非常快。 - Behrooz
4
在提到的条件下,这是有可能的...但结果非常惊人。这里的教训可能只是,不要认为某种方法在所有情况下都最有效。测试和基准测试总能带来新的启示。 - Jeremy Holovacs
@ZachSaw:速度并不是一切。实际上,如果负载是从网络流、文件或数据库中检索的话,反序列化速度通常可以忽略不计。在这种情况下,安全性更为重要。当然,我也创建了自己的多态序列化器,但坦白说,需要注释的非多态序列化器始终更加安全。顺便说一句,我fork了你的fiddle,并将我的序列化器添加到了组中:https://dotnetfiddle.net/K80nIm - György Kőszeg
@GyörgyKőszeg 在这种情况下,速度确实是最重要的,因为这是原始问题的意图。 - Jeremy Holovacs
3
如果是这样,那么我应该很高兴我的序列化程序在这个组中是最快的。不过,我会更加仔细地表述。这是一个11年前的问题,当时对多态序列化器的安全漏洞并没有引起足够的重视。我在这篇答案中收集了一些具体的安全问题。我专注于BinaryFormatter,但很多问题也影响其他序列化器。 - György Kőszeg
显示剩余2条评论

16

另一个声称超级快速的序列化器是netserializer

他们网站上提供的数据显示相对于protobuf,性能提升了2倍-4倍。虽然我没有亲自尝试过,但如果您正在评估各种选项,请也考虑一下这个。


3
我刚在我的应用程序中尝试了NetSerializer,它效果非常好。值得一试。 - Galen
NetSerializer不适合序列化“用户”对象,因为库一开始就不知道类型,甚至没有强制用户将其对象标记为可序列化的选项。 - Zach Saw

16

使用Protobuf有什么缺点吗? - Robert Jeppesen
12
你需要给你的对象加注释。Protobuf 不像序列化器那样存储字段名和类型,而是从你的实际类型中获取它们。这是目标文件更小的原因之一。文档解释了所有这些。我已经使用它一段时间了,如果你需要快速进行序列化和反序列化以及较小的目标文件,Protobuf 真的是一个好选择。 - Pieter van Ginkel
有没有使用C#中的Protobuf编写的完整源代码示例可以添加到答案中? - Kiquenet
它并不是那么快...实际上,与非常非常非常非常快的序列化器相比,它相当慢:https://dotnetfiddle.net/gOqQ7p - Zach Saw
@ZachSaw 如果你只是处理整数数组(就像你的例子),那速度并不会很快,但是很少有人只序列化整数。当你开始处理具有许多成员的嵌套复杂类型时,你会看到速度上的好处(至少我是这样认为的)。 - matt.rothmeyer

6

.Net自带的二进制序列化工具应该比XmlSerializer更快。或者使用另一种序列化工具,如protobuf、json等。

但对于这些工具中的某些,您需要添加属性或其他方式来添加元数据。例如,ProtoBuf在内部使用数字属性ID,需要通过不同的机制进行映射。任何序列化工具都不容易实现版本控制。


是的,它确实非常快,并且处理的情况/类型比Xml更多。 - leppie

4
我纠正了上述代码中的错误,并得到了以下结果: 另外,我不确定 NetSerializer 要求您注册需要序列化的类型,这可能会对兼容性或性能造成什么样的影响。
Generating 100000 arrays of data...
Test data generated.
Testing BinarySerializer...
BinaryFormatter: Serializing took 508.9773ms.
BinaryFormatter: Deserializing took 371.8499ms.

Testing ProtoBuf serializer...
ProtoBuf: Serializing took 3280.9185ms.
ProtoBuf: Deserializing took 3190.7899ms.

Testing NetSerializer serializer...
NetSerializer: Serializing took 427.1241ms.
NetSerializer: Deserializing took 78.954ms.
Press any key to end.

修改后的代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace SerializationTests
{
    class Program
    {
        static void Main(string[] args)
        {
            var count = 100000;
            var rnd = new Random((int)DateTime.UtcNow.Ticks & 0xFF);
            Console.WriteLine("Generating {0} arrays of data...", count);
            var arrays = new List<int[]>();
            for (int i = 0; i < count; i++)
            {
                var elements = rnd.Next(1, 100);
                var array = new int[elements];
                for (int j = 0; j < elements; j++)
                {
                    array[j] = rnd.Next();
                }
                arrays.Add(array);
            }
            Console.WriteLine("Test data generated.");
            var stopWatch = new Stopwatch();

            Console.WriteLine("Testing BinarySerializer...");
            var binarySerializer = new BinarySerializer();
            var binarySerialized = new List<byte[]>();
            var binaryDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                binarySerialized.Add(binarySerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in binarySerialized)
            {
                binaryDeserialized.Add(binarySerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("BinaryFormatter: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);


            Console.WriteLine();
            Console.WriteLine("Testing ProtoBuf serializer...");
            var protobufSerializer = new ProtoBufSerializer();
            var protobufSerialized = new List<byte[]>();
            var protobufDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var array in arrays)
            {
                protobufSerialized.Add(protobufSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in protobufSerialized)
            {
                protobufDeserialized.Add(protobufSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("ProtoBuf: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine();
            Console.WriteLine("Testing NetSerializer serializer...");
            var netSerializerSerialized = new List<byte[]>();
            var netSerializerDeserialized = new List<int[]>();

            stopWatch.Reset();
            stopWatch.Start();
            var netSerializerSerializer = new NS();
            foreach (var array in arrays)
            {
                netSerializerSerialized.Add(netSerializerSerializer.Serialize(array));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Serializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            stopWatch.Reset();
            stopWatch.Start();
            foreach (var serialized in netSerializerSerialized)
            {
                netSerializerDeserialized.Add(netSerializerSerializer.Deserialize<int[]>(serialized));
            }
            stopWatch.Stop();
            Console.WriteLine("NetSerializer: Deserializing took {0}ms.", stopWatch.Elapsed.TotalMilliseconds);

            Console.WriteLine("Press any key to end.");
            Console.ReadKey();
        }

        public class BinarySerializer
        {
            private static readonly BinaryFormatter Formatter = new BinaryFormatter();

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Formatter.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = (T)Formatter.Deserialize(stream);
                    return result;
                }
            }
        }

        public class ProtoBufSerializer
        {
            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    ProtoBuf.Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    var result = ProtoBuf.Serializer.Deserialize<T>(stream);
                    return result;
                }
            }
        }

        public class NS
        {
            NetSerializer.Serializer Serializer = new NetSerializer.Serializer(new Type[] { typeof(int), typeof(int[]) });

            public byte[] Serialize(object toSerialize)
            {
                using (var stream = new MemoryStream())
                {
                    Serializer.Serialize(stream, toSerialize);
                    return stream.ToArray();
                }
            }

            public T Deserialize<T>(byte[] serialized)
            {
                using (var stream = new MemoryStream(serialized))
                {
                    Serializer.Deserialize(stream, out var result);
                    return (T)result;
                }
            }
        }
    }
}

1
你指的是哪些错误? - Jeremy Holovacs

1
你可以尝试使用Salar.Bois序列化器,它具有良好的性能。它的重点在于有效负载大小,但它也提供了良好的性能。
如果您希望查看并比较结果,可以在Github页面上查看基准测试。

https://github.com/salarcode/Bois


0

我已经为您的类输入了CGbR生成器。由于它处于早期阶段,尚不支持DateTime,因此我将其简单地替换为long。生成的序列化代码如下:

public int Size
{
    get 
    { 
        var size = 24;
        // Add size for collections and strings
        size += Cts == null ? 0 : Cts.Count * 4;
        size += Tes == null ? 0 : Tes.Count * 4;
        size += Code == null ? 0 : Code.Length;
        size += Message == null ? 0 : Message.Length;

        return size;              
    }
}

public byte[] ToBytes(byte[] bytes, ref int index)
{
    if (index + Size > bytes.Length)
        throw new ArgumentOutOfRangeException("index", "Object does not fit in array");

    // Convert Cts
    // Two bytes length information for each dimension
    GeneratorByteConverter.Include((ushort)(Cts == null ? 0 : Cts.Count), bytes, ref index);
    if (Cts != null)
    {
        for(var i = 0; i < Cts.Count; i++)
        {
            var value = Cts[i];
            value.ToBytes(bytes, ref index);
        }
    }
    // Convert Tes
    // Two bytes length information for each dimension
    GeneratorByteConverter.Include((ushort)(Tes == null ? 0 : Tes.Count), bytes, ref index);
    if (Tes != null)
    {
        for(var i = 0; i < Tes.Count; i++)
        {
            var value = Tes[i];
            value.ToBytes(bytes, ref index);
        }
    }
    // Convert Code
    GeneratorByteConverter.Include(Code, bytes, ref index);
    // Convert Message
    GeneratorByteConverter.Include(Message, bytes, ref index);
    // Convert StartDate
    GeneratorByteConverter.Include(StartDate.ToBinary(), bytes, ref index);
    // Convert EndDate
    GeneratorByteConverter.Include(EndDate.ToBinary(), bytes, ref index);
    return bytes;
}

public Td FromBytes(byte[] bytes, ref int index)
{
    // Read Cts
    var ctsLength = GeneratorByteConverter.ToUInt16(bytes, ref index);
    var tempCts = new List<Ct>(ctsLength);
    for (var i = 0; i < ctsLength; i++)
    {
        var value = new Ct().FromBytes(bytes, ref index);
        tempCts.Add(value);
    }
    Cts = tempCts;
    // Read Tes
    var tesLength = GeneratorByteConverter.ToUInt16(bytes, ref index);
    var tempTes = new List<Te>(tesLength);
    for (var i = 0; i < tesLength; i++)
    {
        var value = new Te().FromBytes(bytes, ref index);
        tempTes.Add(value);
    }
    Tes = tempTes;
    // Read Code
    Code = GeneratorByteConverter.GetString(bytes, ref index);
    // Read Message
    Message = GeneratorByteConverter.GetString(bytes, ref index);
    // Read StartDate
    StartDate = DateTime.FromBinary(GeneratorByteConverter.ToInt64(bytes, ref index));
    // Read EndDate
    EndDate = DateTime.FromBinary(GeneratorByteConverter.ToInt64(bytes, ref index));

    return this;
}

我创建了一个像这样的示例对象列表:
var objects = new List<Td>();
for (int i = 0; i < 1000; i++)
{
    var obj = new Td
    {
        Message = "Hello my friend",
        Code = "Some code that can be put here",
        StartDate = DateTime.Now.AddDays(-7),
        EndDate = DateTime.Now.AddDays(2),
        Cts = new List<Ct>(),
        Tes = new List<Te>()
    };
    for (int j = 0; j < 10; j++)
    {
        obj.Cts.Add(new Ct { Foo = i * j });
        obj.Tes.Add(new Te { Bar = i + j });
    }
    objects.Add(obj);
}

在我的电脑上使用 Release 构建的结果:

var watch = new Stopwatch();
watch.Start();
var bytes = BinarySerializer.SerializeMany(objects);
watch.Stop();

大小:149000字节

时间:2.059毫秒3.13毫秒

编辑:从CGbR 0.4.3开始,二进制序列化程序支持DateTime。不幸的是,DateTime.ToBinary方法非常慢。我会很快用更快的方法替换它。

编辑2:使用UTC DateTime并调用ToUniversalTime(),性能得到恢复,在1.669毫秒处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接