วิธีที่เร็วที่สุดในการทำให้เป็นอนุกรมและแยกวัตถุ. NET


88

ฉันกำลังมองหาวิธีที่เร็วที่สุดในการทำให้เป็นอนุกรมและแยกวัตถุ. 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 จะทำงานได้เร็วกว่าในเกณฑ์มาตรฐาน
โคดี้เกรย์

ตกลงฉันเข้าใจว่าฉันหมายถึงในแง่ของประสิทธิภาพ ...
aron

มีลิงค์มากมายออกมา หนึ่งเช่นblogs.msdn.com/b/youssefm/archive/2009/07/10/…
nawfal

คำตอบ:


58

นี่คือโมเดลของคุณ (ที่คิดค้นCTและTE) โดยใช้protobuf-net (แต่ยังคงความสามารถในการใช้งานXmlSerializerซึ่งจะมีประโยชน์โดยเฉพาะอย่างยิ่งสำหรับการย้ายข้อมูล) ฉันส่งด้วยความนอบน้อม (พร้อมหลักฐานมากมายหากคุณต้องการ) ว่านี่คือ serializer วัตถุประสงค์ทั่วไปที่เร็วที่สุด (หรือเร็วที่สุด) ใน. NET

หากคุณต้องการสตริงเพียงแค่ base-64 เข้ารหัสไบนารี

[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 รักโปรโตคอลบัฟเฟอร์ที่คุณทำและฉันรู้ว่าโพสต์นี้มีอายุเกือบ 5 ปีแล้ว แต่ netserializer ที่อ้างถึงในคำตอบที่นี่ (Binoj) มีเมตริกที่ระบุว่าการใช้งานของคุณไม่เร็วที่สุด นั่นเป็นคำแถลง / โฆษณาที่เป็นธรรมหรือมีการแลกเปลี่ยนหรือไม่? ขอบคุณ
Jeremy Thompson

ตกลงฉันเห็นตอนนี้ NetSerialization ใช้ได้เฉพาะกับเวอร์ชันเดียวกับที่ฉันกำลังมองหา Version Tolerant Serialization
Jeremy Thompson

1
ใครก็ตามที่คิดว่าสิ่งนี้เร็วต้องสูบบุหรี่บางอย่างอาจเร็วพอสำหรับหลาย ๆ กรณีและอาจเร็วกว่าอนุกรมอื่น ๆ จำนวนมาก แต่มันเร็วจริง ๆ เมื่อเทียบกับการแยกวิเคราะห์ด้วยตนเองหรือไม่? พระเจ้าของฉันไม่
BjarkeCK

@BjarkeCK serializers มีส่วนเกี่ยวข้องมากขึ้นเล็กน้อยเนื่องจากพวกเขาต้องทำหลายอย่างเพื่อป้องกันไม่ให้คนยิงเท้าของตัวเองออก (โดยเฉพาะอย่างยิ่งเมื่อพวกเขาทำซ้ำเวอร์ชัน) คนส่วนใหญ่ไม่ต้องการใช้ชีวิตของพวกเขาในการแก้ไขข้อบกพร่องของรหัสซีเรียลไลเซชันดังนั้น: serializer ที่ดี - ในขณะที่ช้ากว่าการใช้งานด้วยตนเองที่ไม่สามารถใช้งานเวอร์ชันที่ใช้งานได้อย่างสมบูรณ์แบบ - มักจะเป็นการประนีประนอมที่ดีสำหรับคนส่วนใหญ่
Marc Gravell

2
@BjarkeCK ฉันไม่เห็นด้วยอย่างยิ่ง; นั่นไม่ได้มีประโยชน์จากระยะไกลสำหรับคนส่วนใหญ่ อะไรต่อไป - เขียนคอลเลกชันของเราเองทุกวัน? No: ทำสิ่งนี้ได้ดีพอสมควรแม้จะเป็นเรื่องยาก แน่นอนว่าถ้าคุณต้องการผลลัพธ์ที่เร็วที่สุดมากจริง: คุณกำลังไปได้ที่จะได้รับในมือของคุณสกปรก - แต่สำหรับคนส่วนใหญ่การทำเช่นนี้จะเป็นจริงเสียที่ไม่ดีของเวลาของพวกเขา ดีที่สุดมันจะใช้เวลานานกว่านี้มาก มีแนวโน้มว่าโค้ดของพวกเขาจะมีข้อบกพร่องไม่น่าเชื่อถือและอาจช้ากว่าการใช้ไลบรารีที่มีอยู่ คนส่วนใหญ่ควรให้ความสำคัญกับสิ่งที่แอปต้องการไม่ใช่ข้อเสนอแนะนี้
Marc Gravell

34

การเปรียบเทียบเชิงเปรียบเทียบระหว่างรูปแบบที่แตกต่างกันที่ฉันสร้างขึ้นในโพสต์นี้ - https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

เพียงตัวอย่างเดียวจากโพสต์ - ใส่คำอธิบายภาพที่นี่


6
นั่นไม่ใช่ความเร็ว นั่นคือความช้า มีข้อความว่า "เล็กดีกว่า" ในบทความที่ลิงก์
Timur Nuriyasov

2
@TimurNuriyasov นั่นคือเวลาที่ใช้ในการดำเนินการ
Maxim

2
คุณบอกว่าไบนารีช้าที่สุด? ฉันไม่คิดอย่างนั้น! ฉันเดาถูกต้องหมายถึงความเร็วไม่ใช่เวลา
Javid

2
ไบนารีช้าที่สุด ลองด้วยตัวคุณเอง แต่ฉันจะบอกว่ามันง่ายที่สุดเพราะไม่ต้องใช้การแก้ไขสิ่งต่างๆที่กำหนดเองเพื่อให้ทำงานกับวัตถุหลายรูปแบบได้อย่างถูกต้อง (อินเทอร์เฟซ ฯลฯ )
Kamarey

1
@ Kamarey ดูการทดสอบของฉันด้านล่าง ... ไบนารีเป็นวิธีที่เร็วกว่าวิธีอื่น ๆ
Jeremy Holovacs

20

ด้วยความสนใจในเรื่องนี้ฉันจึงตัดสินใจทดสอบวิธีการที่แนะนำด้วยการทดสอบ "แอปเปิ้ลถึงแอปเปิ้ล" ที่ใกล้เคียงที่สุดเท่าที่จะทำได้ ฉันเขียนแอปคอนโซลด้วยรหัสต่อไปนี้:

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.

ดังนั้นข้อสรุปของฉันคือ: อาจมีบางกรณีที่ ProtoBuf และ NetSerializer เหมาะสมกัน แต่ในแง่ของประสิทธิภาพดิบสำหรับวัตถุอย่างน้อยที่ค่อนข้างเรียบง่าย ... BinaryFormatter มีประสิทธิภาพมากกว่าอย่างมีนัยสำคัญโดยอย่างน้อยตามลำดับขนาด

YMMV.


1
บางที BinaryFormatter ก็เร็วมากกับอาร์เรย์
Behrooz

4
เป็นไปได้ ... แต่ภายใต้เงื่อนไขที่กล่าวมาผลลัพธ์นั้นน่าทึ่งมาก บทเรียนที่นี่อาจเป็นเพียงอย่าเชื่อว่าวิธีการหนึ่งมีประสิทธิภาพมากที่สุดในทุกสถานการณ์ การทดสอบและการเปรียบเทียบจะให้ความกระจ่างเสมอ
Jeremy Holovacs

ในการทำให้อนุกรมวัตถุ C ++ เร็วขึ้นประมาณ 100 เท่า!
Mario M

น่าสนใจมาก! ทุกคนอ้างว่าโปรโตบัฟเร็วที่สุด แต่สิ่งนี้แสดงให้เห็นอย่างชัดเจนว่ามันช้าอย่างเจ็บปวด ฉันเพิ่ม BinaronSerializer ลงในส่วนผสมที่นี่dotnetfiddle.net/gOqQ7p - เร็วกว่า BinaryFormatter เกือบสองเท่าซึ่งเร็วมากกับอาร์เรย์
Zach Saw

16

โปรโตบุฟเร็วมาก

ดูhttp://code.google.com/p/protobuf-net/wiki/Performanceสำหรับข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพของระบบนี้และการใช้งาน


มีข้อเสียในการใช้ Protobuf หรือไม่?
Robert Jeppesen

11
คุณต้องใส่คำอธิบายประกอบวัตถุของคุณ Protobuf ไม่ได้จัดเก็บชื่อและประเภทของฟิลด์เหมือนที่ serializers ทำ แต่นำมาจากประเภทจริงของคุณ นี่เป็นสาเหตุหนึ่งที่ไฟล์เป้าหมายมีขนาดเล็กลงมาก เอกสารอธิบายทั้งหมดนี้ ฉันใช้มันมาระยะหนึ่งแล้วและหากคุณต้องการการทำให้เป็นอนุกรมที่รวดเร็ว (de) และไฟล์เป้าหมายขนาดเล็ก protobuf เป็นหนทางที่จะไปจริงๆ
Pieter van Ginkel

ตัวอย่างซอร์สโค้ดแบบเต็มโดยใช้ Protobut ใน C # เพื่อเพิ่มคำตอบหรือไม่
Kiquenet

มันไม่เร็วขนาดนั้น ... อันที่จริงมันค่อนข้างช้าเมื่อเทียบกับ serializers ที่เร็วมาก ๆ : dotnetfiddle.net/gOqQ7p
Zach Saw

@ZachSaw มันไม่เร็วเท่าไหร่ถ้าคุณแค่จัดการกับอาร์เรย์ของจำนวนเต็ม (ตัวอย่างของคุณ) แต่มีเพียงไม่กี่คนเท่านั้นที่จัดลำดับเลขจำนวนเต็ม คุณจะเห็นประโยชน์ของความเร็ว (หรืออย่างน้อยฉันก็ทำ) เมื่อคุณเริ่มจัดการกับประเภทที่ซับซ้อนซ้อนกันซึ่งมีสมาชิกจำนวนมาก
matt.rothmeyer

15

แต่ serializer อื่นออกมีที่อ้างว่าเป็นเร็วสุดคือnetserializer

ข้อมูลที่ให้ในไซต์ของพวกเขาแสดงประสิทธิภาพ2x - 4x เหนือโปรโตบัฟฉันไม่ได้ลองด้วยตัวเอง แต่ถ้าคุณกำลังประเมินตัวเลือกต่างๆให้ลองทำเช่นกัน


3
ฉันเพิ่งลองใช้ NetSerializer ในแอปพลิเคชันของฉันและมันใช้งานได้อย่างมหัศจรรย์ น่าลอง
Galen

netserializer ไม่เหมาะสำหรับการทำให้ออบเจ็กต์ "ผู้ใช้" เป็นอนุกรมโดยที่ไลบรารีไม่ทราบว่าจะเริ่มต้นด้วยประเภทใดหรือแม้กระทั่งมีตัวเลือกในการบังคับให้ผู้ใช้ทำเครื่องหมายวัตถุของตนว่าเป็นอนุกรมได้
Zach Saw

6

อนุกรมไบนารีที่มาพร้อมกับ. net ควรเร็วกว่า XmlSerializer หรือ serializer อื่นสำหรับ protobuf, json, ...

แต่สำหรับบางคนคุณต้องเพิ่มแอตทริบิวต์หรือวิธีอื่นในการเพิ่มข้อมูลเมตา ตัวอย่างเช่น ProtoBuf ใช้รหัสคุณสมบัติตัวเลขภายในและการแม็ปจะต้องได้รับการอนุรักษ์โดยกลไกอื่น การกำหนดเวอร์ชันไม่ใช่เรื่องสำคัญสำหรับซีเรียลไลเซอร์ใด ๆ


ใช่มันเร็วมากและจัดการกรณี / ประเภทได้มากกว่า Xml
leppie

1

ฉันลบข้อบกพร่องในโค้ดด้านบนและได้ผลลัพธ์ด้านล่าง: นอกจากนี้ฉันไม่แน่ใจว่า 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

0

คุณสามารถลองSalar.Bois serializer ซึ่งมีประสิทธิภาพที่ดี โฟกัสอยู่ที่ขนาดน้ำหนักบรรทุก แต่ยังให้ประสิทธิภาพที่ดี

มีการวัดประสิทธิภาพในหน้า 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วิธีนี้ช้ามาก ฉันจะแทนที่มันด้วยการทำให้เร็วขึ้นเร็ว ๆ นี้

Edit2:เมื่อใช้ UTC DateTimeโดยเรียกToUniversalTime()ผลการดำเนินงานมีการเรียกคืนและนาฬิกาใน1.669ms

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.