Cách nhanh nhất để tuần tự hóa và giải mã hóa các đối tượng .NET


87

Tôi đang tìm cách nhanh nhất để tuần tự hóa và giải mã hóa các đối tượng .NET. Đây là những gì tôi có cho đến nay:

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
Hiệu suất hoặc mã in chân?
ulrichb

Bạn đang hỏi tôi có cần dữ liệu hiệu suất hoặc mã không?
aron

3
Anh ấy đang hỏi nếu "cách nhanh nhất", ý bạn là về hiệu suất hay về dấu vết mã. BinaryFormatterlà cực kỳ nhanh về mã và triển khai, nhưng một giải pháp như của Marc sẽ hoạt động nhanh hơn trong điểm chuẩn.
Cody Grey

ok, tôi hiểu rồi, ý tôi là về mặt hiệu suất ...
aron

Có rất nhiều liên kết ra khỏi đó. Một ví dụ: blogs.msdn.com/b/youssefm/archive/2009/07/10/...
nawfal

Câu trả lời:


57

Đây là mô hình của bạn (được phát minh CTTE) sử dụng protobuf-net (nhưng vẫn giữ được khả năng sử dụng XmlSerializer, có thể hữu ích - đặc biệt là cho việc di chuyển); Tôi khiêm tốn đệ trình (với nhiều bằng chứng nếu bạn cần) rằng đây trình tuần tự hóa mục đích chung nhanh nhất (hoặc chắc chắn là nhanh nhất) trong .NET.

Nếu bạn cần chuỗi, chỉ cần mã hóa base-64 thành nhị phân.

[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
G'day Marc, yêu thích công việc bộ đệm giao thức mà bạn đã thực hiện và tôi biết bài đăng này đã gần 5 năm tuổi nhưng netserializer được trích dẫn trong một câu trả lời ở đây (Binoj) có các số liệu cho thấy việc triển khai của bạn không phải là nhanh nhất. Đó có phải là một tuyên bố / quảng cáo công bằng hay là có sự đánh đổi? cảm ơn
Jeremy Thompson

ok tôi thấy bây giờ, NetSerialization chỉ hoạt động cho cùng một phiên bản nơi như tôi đang tìm kiếm Version chịu serialization
Jeremy Thompson

1
Bất kỳ ai nghĩ rằng tốc độ này nhanh hẳn là đang hút một thứ gì đó, nó có thể đủ nhanh cho nhiều trường hợp và có thể nhanh hơn rất nhiều các tuần tự hóa khác ngoài kia, nhưng liệu nó có thực sự nhanh, so với việc phân tích cú pháp thủ công? Chúa ơi không.
BjarkeCK

@BjarkeCK serializers vốn dĩ có liên quan nhiều hơn một chút, vì họ cần phải làm nhiều thứ để ngăn mọi người tự bắn vào chân của họ (đặc biệt là khi họ lặp lại các phiên bản); hầu hết mọi người không muốn dành cả cuộc đời để gỡ lỗi mã tuần tự hóa, vì vậy: một trình tuần tự hóa tốt - trong khi chắc chắn chậm hơn so với việc triển khai thủ công không dung nạp phiên bản được triển khai hoàn hảo - thường là một thỏa hiệp tốt cho hầu hết mọi người
Marc Gravell

1
@BjarkeCK Tôi hoàn toàn không đồng ý; điều đó thậm chí không hữu ích từ xa cho hầu hết mọi người. Điều gì tiếp theo - viết bộ sưu tập của riêng chúng tôi mỗi ngày? Không: làm công việc này một cách hợp lý cũng rất khó . Chắc chắn, nếu bạn thực sự cần đầu ra nhanh nhất: bạn sẽ phải làm bẩn tay - nhưng đối với hầu hết mọi người, làm điều này thực sự lãng phí thời gian của họ. TỐT NHẤT sẽ mất nhiều thời gian hơn nữa. Nhiều khả năng mã của họ sẽ có lỗi, không đáng tin cậy và có thể chậm hơn so với việc sử dụng các thư viện có sẵn. Hầu hết mọi người nên tập trung vào những gì ứng dụng của họ cần , không phải điều nhỏ nhặt này.
Marc Gravell

33

Một so sánh chuyên sâu giữa các định dạng khác nhau do tôi thực hiện trong bài đăng này- https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Chỉ một mẫu từ bài đăng- nhập mô tả hình ảnh ở đây


5
Đó không phải là tốc độ. Đó là sự chậm chạp. Nó nói "nhỏ hơn là tốt hơn" trong bài báo được liên kết.
Timur Nuriyasov

2
@TimurNuriyasov, đó là thời gian cần thiết để thực hiện phẫu thuật
Maxim

2
Vì vậy, bạn nói nhị phân là chậm nhất? Tôi không nghĩ vậy! Tôi đoán chính xác nó đề cập đến tốc độ, không phải thời gian.
Javid

2
Nhị phân là chậm nhất. Cố gắng bản thân. Nhưng tôi sẽ nói đó là dễ dàng nhất, vì nó không yêu cầu giải quyết công cụ để một cách chính xác làm việc với các đối tượng đa hình (giao diện, vv) bất kỳ tùy chỉnh
Kamarey

1
@Kamarey nhìn vào bài kiểm tra của tôi dưới đây ... nhị phân là cách nhanh hơn so với những người khác.
Jeremy Holovacs

19

Có hứng thú với điều này, tôi quyết định thử nghiệm các phương pháp được đề xuất với thử nghiệm "táo với táo" gần nhất mà tôi có thể. Tôi đã viết một ứng dụng Bảng điều khiển, với mã sau:

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);
            }
        }
    }
}

Kết quả làm tôi ngạc nhiên; chúng nhất quán khi chạy nhiều lần:

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.

Thu thập những kết quả này, tôi quyết định xem liệu ProtoBuf hoặc NetSerializer có hoạt động tốt hơn với các đối tượng lớn hơn hay không. Tôi đã thay đổi số lượng bộ sưu tập thành 10.000 đối tượng, nhưng tăng kích thước của mảng lên 1-10.000 thay vì 1-100. Kết quả thậm chí còn rõ ràng hơn:

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.

Do đó, kết luận của tôi là: có thể có những trường hợp ProtoBuf và NetSerializer rất phù hợp, nhưng xét về hiệu suất thô cho ít nhất các đối tượng tương đối đơn giản ... BinaryFormatter có hiệu suất cao hơn đáng kể, ít nhất là một bậc của độ lớn.

YMMV.


1
có lẽ BinaryFormatter chỉ thực sự nhanh chóng với các mảng.
Behrooz

4
Có thể ... nhưng với những điều kiện đã đề cập, kết quả thật ấn tượng. Bài học ở đây có thể chỉ là, đừng tin rằng một phương pháp là hiệu quả nhất trong mọi trường hợp. Kiểm tra và điểm chuẩn luôn luôn soi sáng.
Jeremy Holovacs

Trong C ++, tuần tự hóa đối tượng nhanh hơn khoảng 100 lần!
Mario M

Rất thú vị! Mọi người đều khẳng định protobuf là nhanh nhất nhưng điều này cho thấy rõ ràng là nó rất chậm. Tôi đã thêm BinaronSerializer của mình vào hỗn hợp tại đây dotnetfiddle.net/gOqQ7p - nó nhanh hơn gần gấp đôi so với BinaryFormatter, vốn đã thực sự nhanh với các mảng.
Zach Saw

16

Protobuf rất nhanh.

Xem http://code.google.com/p/protobuf-net/wiki/Performance để biết thông tin chuyên sâu về hiệu suất của hệ thống này và cách triển khai.


Có bất kỳ hạn chế nào khi sử dụng Protobuf không?
Robert Jeppesen

11
Bạn phải chú thích các đối tượng của mình. Protobuf không lưu trữ tên trường và kiểu như trình tuần tự hóa, mà lấy chúng từ kiểu thực của bạn. Đây là một trong những lý do khiến các tệp đích nhỏ hơn nhiều. Tài liệu giải thích tất cả điều này. Tôi đã sử dụng nó một thời gian rồi, và nếu bạn cần tuần tự hóa nhanh (de) và các tệp mục tiêu nhỏ, thì protobuf thực sự là cách để đi.
Pieter van Ginkel

Bất kỳ mẫu mã nguồn đầy đủ nào sử dụng Protobut trong C # để thêm vào câu trả lời?
Kiquenet

Nó không nhanh như vậy ... Trên thực tế, nó khá chậm so với các bộ nối tiếp rất nhanh rất nhanh: dotnetfiddle.net/gOqQ7p
Zach Saw

@ZachSaw không nhanh bằng nếu bạn chỉ xử lý mảng các số nguyên (ví dụ của bạn), nhưng rất ít người chỉ sắp xếp các số nguyên. Bạn thấy những lợi ích về tốc độ (hoặc ít nhất là tôi làm), khi bạn bắt đầu xử lý các kiểu phức tạp lồng nhau với nhiều thành viên.
matt.rothmeyer

15

Tuy nhiên, một bộ nối tiếp khác được tuyên bố là siêu nhanh là netserializer .

Dữ liệu được cung cấp trên trang web của họ cho thấy hiệu suất gấp 2 - 4 lần so với protobuf , tôi chưa thử điều này bản thân mình, nhưng nếu bạn đang đánh giá các tùy chọn khác nhau, hãy thử điều này.


3
Tôi vừa thử NetSerializer trong ứng dụng của mình và nó hoạt động rất tốt. Lần thử thách này thật có giá trị.
Galen

netserializer không phù hợp để tuần tự hóa các đối tượng "người dùng" trong đó thư viện không biết loại bắt đầu là gì, hoặc thậm chí có tùy chọn buộc người dùng đánh dấu các đối tượng của họ là có thể tuần tự hóa.
Zach Saw

6

Bộ tuần tự nhị phân đi kèm với .net sẽ nhanh hơn XmlSerializer. Hoặc một bộ nối tiếp khác cho protobuf, json, ...

Nhưng đối với một số người trong số họ, bạn cần thêm Thuộc tính hoặc một số cách khác để thêm siêu dữ liệu. Ví dụ: ProtoBuf sử dụng nội bộ ID thuộc tính số và ánh xạ cần phải được bảo toàn bằng một cơ chế khác. Việc tạo phiên bản không hề nhỏ với bất kỳ bộ nối tiếp nào.


Có, nó thực sự rất nhanh và nó xử lý nhiều trường hợp / loại hơn Xml.
leppie

1

Tôi đã loại bỏ các lỗi trong đoạn mã trên và nhận được kết quả bên dưới: Ngoài ra, tôi không chắc về cách NetSerializer yêu cầu bạn đăng ký các loại bạn đang tuần tự hóa, loại khả năng tương thích hoặc hiệu suất khác biệt có thể tạo ra.

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.

Mã sửa đổi

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
Bạn đang đề cập đến lỗi nào?
Jeremy Holovacs

0

Bạn có thể thử bộ tuần tự Salar.Bois có hiệu suất khá. Nó tập trung vào kích thước tải trọng nhưng nó cũng mang lại hiệu suất tốt.

Có các điểm chuẩn trên trang Github nếu bạn muốn tự mình xem và so sánh kết quả.

https://github.com/salarcode/Bois


0

Tôi đã tự do đưa các lớp học của bạn vào trình tạo CGbR .Bởi vì nó đang ở giai đoạn đầu nó chưa hỗ trợ DateTime, vì vậy tôi chỉ cần thay thế nó bằng dài. Mã tuần tự hóa được tạo trông giống như sau:

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;
}

Tôi đã tạo một danh sách các đối tượng mẫu như sau:

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);
}

Kết quả trên máy của tôi trong bản Releasedựng:

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

Kích thước: 149000 byte

Thời gian: 2.059 mili giây 3,13ms

Chỉnh sửa: Bắt đầu với CGbR 0.4.3 bộ tuần tự nhị phân hỗ trợ DateTime. Thật không may, DateTime.ToBinaryphương pháp này cực kỳ chậm. Tôi sẽ sớm thay thế nó bằng somehting nhanh hơn.

Edit2: Khi sử dụng UTC DateTimebằng cách gọi ToUniversalTime(), hiệu suất được khôi phục và đồng hồ ở 1.669ms .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.