Cara tercepat untuk membuat serial dan deserialisasi objek .NET

88

Saya mencari cara tercepat untuk membuat serial dan deserialisasi objek NET. Inilah yang saya miliki sejauh ini:

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);
    }        
}
aron
sumber
2
Performa atau kode foot print?
ulrichb
Apakah Anda bertanya kepada saya apakah saya memerlukan data atau kode kinerja?
aron
3
Dia bertanya apakah, dengan "cara tercepat," yang Anda maksud dalam hal kinerja atau dalam istilah jejak kode. BinaryFormattersangat cepat dalam hal kode dan implementasi, tetapi solusi seperti Marc akan bekerja lebih cepat dalam tolok ukur.
Cody Gray
ok, begitu, maksud saya dalam hal kinerja ...
aron
Ada banyak tautan di luar sana. Salah satu seperti: blogs.msdn.com/b/youssefm/archive/2009/07/10/...
Naufal

Jawaban:

58

Berikut model Anda (dengan ditemukan CTdan TE) menggunakan protobuf-net (namun tetap memiliki kemampuan untuk menggunakan XmlSerializer, yang dapat berguna - khususnya untuk migrasi); Saya dengan rendah hati mengirimkan (dengan banyak bukti jika Anda membutuhkannya) bahwa ini adalah serializer tujuan umum tercepat (atau pasti salah satu tercepat) di .NET.

Jika Anda membutuhkan string, cukup base-64 mengenkode biner.

[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);
        }
    }
}
Marc Gravell
sumber
2
G'day Marc, suka pekerjaan buffer-protokol yang telah Anda lakukan dan saya tahu posting ini hampir berusia 5 tahun tetapi netserializer yang dikutip dalam jawaban di sini (Binoj) memiliki metrik yang menunjukkan bahwa implementasi Anda bukanlah yang tercepat. Apakah itu pernyataan / iklan yang adil atau ada trade off? terima kasih
Jeremy Thompson
ok saya lihat sekarang, NetSerialization hanya berfungsi untuk versi yang sama dimana saya mencari Version Tolerant Serialization
Jeremy Thompson
1
Siapa pun yang berpikir ini cepat pasti sedang merokok sesuatu, mungkin cukup cepat untuk banyak kasus, dan mungkin lebih cepat daripada banyak serialisasi lain di luar sana, tetapi apakah ini sebenarnya cepat, dibandingkan dengan menguraikannya secara manual? Tuhanku tidak.
BjarkeCK
Pembuat serial @BjarkeCK secara inheren sedikit lebih terlibat, karena mereka perlu melakukan banyak hal untuk mencegah orang menembak kaki mereka sendiri (terutama karena mereka mengulang versi); kebanyakan orang tidak ingin menghabiskan hidup mereka men-debug kode serialisasi, jadi: serializer yang baik - meski pasti lebih lambat daripada implementasi manual versi-intoleran yang diterapkan dengan sempurna - biasanya merupakan kompromi yang baik bagi kebanyakan orang
Marc Gravell
2
@Bjonk Saya sangat tidak setuju; itu tidak bahkan jauh berguna bagi kebanyakan orang. Apa selanjutnya - menulis koleksi kita sendiri setiap hari? Tidak: melakukan hal ini bahkan dengan cukup baik itu sulit . Tentu, jika Anda benar-benar membutuhkan output sangat cepat: Anda akan harus mendapatkan kotor tangan Anda - tetapi bagi kebanyakan orang, melakukan hal ini akan menjadi benar-benar buang yang buruk dari waktu mereka. AT BEST itu akan memakan waktu lebih lama. Kemungkinan besar, kode mereka akan bermasalah, tidak dapat diandalkan, dan mungkin lebih lambat daripada menggunakan pustaka yang tersedia. Kebanyakan orang harus berkonsentrasi pada apa yang dibutuhkan aplikasi mereka , bukan pada hal-hal kecil ini.
Marc Gravell
34

Perbandingan komprehensif antara format berbeda yang dibuat oleh saya di posting ini- https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Hanya satu sampel dari pos- masukkan deskripsi gambar di sini

Pepatah
sumber
6
Itu bukan kecepatan. Itu kelambatan. Dikatakan "lebih kecil lebih baik" dalam artikel terkait.
Timur Nuriyasov
2
@TimurNuriyasov, itulah waktu yang dibutuhkan untuk melakukan operasi
Maxim
2
Jadi Anda bilang biner adalah yang paling lambat? Saya rasa tidak! Saya rasa ini benar mengacu pada kecepatan, bukan waktu.
Javid
2
Biner adalah yang paling lambat. Coba sendiri. Tapi saya akan mengatakan itu paling mudah, karena tidak memerlukan hal-hal penyelesaian khusus untuk bekerja dengan benar dengan objek polimorfik (antarmuka, dll)
Kamarey
1
@Kamarey lihat pengujian saya di bawah ini ... biner jauh lebih cepat dari yang lain.
Jeremy Holovacs
20

Karena tertarik dengan hal ini, saya memutuskan untuk menguji metode yang disarankan dengan tes "apel terhadap apel" yang paling mendekati yang saya bisa. Saya menulis aplikasi Konsol, dengan kode berikut:

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

Hasilnya mengejutkan saya; mereka konsisten ketika dijalankan beberapa kali:

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.

Mengumpulkan hasil ini, saya memutuskan untuk melihat apakah ProtoBuf atau NetSerializer bekerja lebih baik dengan objek yang lebih besar. Saya mengubah jumlah koleksi menjadi 10.000 objek, tetapi meningkatkan ukuran array menjadi 1-10.000, bukan 1-100. Hasilnya tampak lebih pasti:

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.

Kesimpulan saya, oleh karena itu, adalah: mungkin ada kasus di mana ProtoBuf dan NetSerializer cocok untuk itu, tetapi dalam hal kinerja mentah untuk setidaknya objek yang relatif sederhana ... BinaryFormatter secara signifikan lebih berkinerja, setidaknya dengan urutan besarnya.

YMMV.

Jeremy Holovacs
sumber
1
mungkin BinaryFormatter sangat cepat dengan array.
Behrooz
4
Itu mungkin ... tetapi dalam kondisi yang disebutkan, hasilnya dramatis. Pelajarannya di sini mungkin saja, jangan percaya satu metode adalah yang paling berhasil dalam semua keadaan. Pengujian dan pembandingan selalu mencerahkan.
Jeremy Holovacs
Dalam C ++ serialisasi objek sekitar 100 kali lebih cepat!
Mario M
Sangat menarik! Semua orang mengklaim protobuf sebagai yang tercepat tetapi ini jelas menunjukkan itu sangat lambat. Saya menambahkan BinaronSerializer saya ke dalam campuran di sini dotnetfiddle.net/gOqQ7p - hampir dua kali lebih cepat dari BinaryFormatter, yang sudah sangat cepat dengan array.
Zach Melihat
16

Protobuf sangat sangat cepat.

Lihat http://code.google.com/p/protobuf-net/wiki/Performance untuk informasi mendalam tentang kinerja sistem ini, dan implementasinya.

Pieter van Ginkel
sumber
Apakah ada kekurangan menggunakan Protobuf?
Robert Jeppesen
11
Anda harus memberi anotasi pada objek Anda. Protobuf tidak menyimpan nama dan tipe field seperti yang dilakukan serializers, tapi mengambilnya dari tipe sebenarnya. Inilah salah satu alasan mengapa ukuran file target jauh lebih kecil. Dokumentasi menjelaskan semua ini. Saya telah menggunakannya untuk beberapa waktu sekarang, dan jika Anda membutuhkan serialisasi cepat (de) dan file target kecil, protobuf adalah cara yang tepat.
Pieter van Ginkel
Ada contoh kode sumber lengkap yang menggunakan Protobut di C # untuk ditambahkan ke jawabannya?
Kiquenet
Tidak secepat itu ... Faktanya, ini cukup lambat dibandingkan dengan serializers yang sangat sangat sangat cepat: dotnetfiddle.net/gOqQ7p
Zach Saw
@ZachSaw tidak secepat jika Anda hanya berurusan dengan array integer (contoh Anda), tetapi sangat sedikit orang yang hanya membuat serial integer. Anda melihat manfaat kecepatan (atau setidaknya saya lakukan), ketika Anda mulai berurusan dengan tipe kompleks bersarang dengan banyak anggota.
matt.rothmeyer
15

Namun serializer lain di luar sana yang mengklaim super cepat adalah netserializer .

Data yang diberikan di situs mereka menunjukkan kinerja 2x - 4x lebih dari protobuf , saya belum mencobanya sendiri, tetapi jika Anda mengevaluasi berbagai opsi, coba ini juga

Binoj Antony
sumber
3
Saya baru saja mencoba NetSerializer di aplikasi saya dan hasilnya luar biasa. Layak dicoba.
Galen
netserializer tidak cocok untuk membuat serial objek "pengguna" di mana perpustakaan tidak tahu apa jenisnya untuk memulai, atau bahkan memiliki opsi untuk memaksa pengguna untuk menandai objek mereka sebagai dapat diserialkan.
Zach Melihat
6

Serializer biner yang disertakan dengan .net harus lebih cepat dari XmlSerializer. Atau serializer lain untuk protobuf, json, ...

Tetapi untuk beberapa di antaranya Anda perlu menambahkan Atribut, atau cara lain untuk menambahkan metadata. Misalnya ProtoBuf menggunakan ID properti numerik secara internal, dan pemetaan harus dipertahankan oleh mekanisme yang berbeda. Pembuatan versi tidak sepele dengan serializer apa pun.

CodesInChaos
sumber
Ya, ini memang sangat cepat, dan menangani lebih banyak kasus / tipe daripada Xml.
leppie
1

Saya menghapus bug dalam kode di atas dan mendapatkan hasil di bawah ini: Juga saya tidak yakin mengingat bagaimana NetSerializer mengharuskan Anda untuk mendaftarkan jenis yang Anda buat serialisasi, jenis kompatibilitas atau perbedaan kinerja apa yang berpotensi membuat.

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.

Kode yang Dimodifikasi

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;
                }
            }
        }
    }
}
John Heilman
sumber
1
Bug apa yang Anda maksud?
Jeremy Holovacs
0

Anda dapat mencoba Salar.Bois serializer yang memiliki kinerja yang layak. Fokusnya adalah pada ukuran muatan tetapi juga menawarkan kinerja yang baik.

Ada tolok ukur di halaman Github jika Anda ingin melihat dan membandingkan hasilnya sendiri.

https://github.com/salarcode/Bois

Salar
sumber
0

Saya memberanikan diri memberi makan kelas Anda ke generator CGbR .Karena masih tahap awal belum support DateTime, jadi saya ganti saja dengan long. Kode serialisasi yang dihasilkan terlihat seperti ini:

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

Saya membuat daftar objek sampel seperti ini:

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

Hasil di mesin saya dalam Releasepembuatan:

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

Ukuran: 149000 byte

Waktu: 2.059ms 3,13 md

Sunting: Dimulai dengan CGbR 0.4.3, serializer biner mendukung DateTime. Sayangnya DateTime.ToBinarymetodenya sangat lambat. Saya akan segera menggantinya dengan sesuatu yang lebih cepat.

Sunting2: Saat menggunakan UTC DateTimedengan meminta ToUniversalTime()kinerja dipulihkan dan jam masuk pada 1.669ms .

Toxantron
sumber