Производительность protobuf-net против DataContractSerializer по сравнению с WCF - PullRequest
4 голосов
/ 26 апреля 2011

Я протестировал сериализацию protobuf, и кажется, что для объектов с определенным количеством он медленнее, чем обычная сериализация данных.Размер передачи больше с использованием DataContractSerializer, но во время сериализации и десериализации быстрее использовать DataContractSerializer

Как вы думаете, это нормально или я допустил ошибку?

[DataContract]
public partial class Toto
{
    [DataMember]
    public string NomToto { get; set; }

    [DataMember]
    public string PrenomToto { get; set; }
} 

вот мой класс для datacontract это то же самое для protobuf

[ProtoContract]
public partial class Titi
{
    [ProtoMember(1)]
    public string NomTiti { get; set; }

    [ProtoMember(2)]
    public string PrenomTiti { get; set; }
}

вот мои методы для служб WCF с protobuf (то же самое для datacontract без ms)

public class TitiService : ITitiService
{
    public byte[] GetAllTitis()
    {
        List<Titi> titiList = new List<Titi>();
        for (int i = 0; i < 20000; i++)
        {
            var titi = new Titi
            {
                NomTiti = "NomTiti" + i,
                PrenomTiti = "PrenomTiti" + i
            };
            titiList.Add(titi);
        }
        var ms = new MemoryStream();
        Serializer.Serialize(ms, titiList);

        byte[] arr = ms.ToArray();
        return arr;
    }
}

Служба с datacontract

public class TotoService : ITotoService
{
    public List<Toto> GetAllTotos()
    {
        List<Toto> totoList = new List<Toto>();
        for (int i = 0; i<20000; i++)
        {
            var toto = new Toto
            {
                NomToto = "NomToto" + i,
                PrenomToto = "PrenomToto" + i
            };
            totoList.Add(toto);
        }
        return totoList;
    }
}

вот клиентский вызов

    public partial class Program
{
    static ProtobufTestAzure.Client.TitiService.TitiServiceClient TitiClient;
    static ProtobufTestAzure.Client.TotoService.TotoServiceClient TotoClient;

    public static void Main(string[] args)
    {
        Stopwatch stopwatch1 = new Stopwatch();
        Stopwatch stopwatch2 = new Stopwatch();
        Stopwatch stopwatch3 = new Stopwatch();

        stopwatch1.Start();

        TitiClient = new ProtobufTestAzure.Client.TitiService.TitiServiceClient();
        Byte[] titiByte = TitiClient.GetAllTitis();
        TitiClient.Close();

        stopwatch1.Stop();


        stopwatch2.Start();

        var ms = new MemoryStream(titiByte);
        List<Titi> TitiList = Serializer.Deserialize<List<Titi>>(ms);

        stopwatch2.Stop();

        Console.WriteLine(" ");

        stopwatch3.Start();

        TotoClient = new ProtobufTestAzure.Client.TotoService.TotoServiceClient();
        var TotoList = TotoClient.GetAllTotos();
        TotoClient.Close();

        stopwatch3.Stop();

        Console.WriteLine("Time elapse for reception (Protobuf): {0} ms ({1} éléments)", stopwatch1.ElapsedMilliseconds, TitiList.Count);
        Console.WriteLine("Time elapse for deserialization (Protobuf : {0} ms ({1} éléments)", stopwatch2.ElapsedMilliseconds, TitiList.Count);
        Console.WriteLine("Time elapse for réception (Datacontract Serialization) : {0} ms ({1} éléments)", stopwatch3.ElapsedMilliseconds, TotoList.Count);

        Console.ReadLine();
    }
}

и результат для 10000 объектов

Время истечения для приема (Protobuf): 3359 мс (10000 элементов) Время истечения для десериализации (Protobuf): 138 мс (10000 элементов) Время истечения для приема (сериализация Datacontract): 2200 мс (10000 элементов)

Я проверяю его с 20000 объектами Это дало мнедля первого вызова

Время истечения приема (Protobuf): 11258 мс (20000 элементов) Время истечения времени для десериализации (Protobuf): 133 мс (20000 элементов) Время истечения для приема (сериализация данных): 3726 мс (20000 элементов)

для второго вызова

Время истечения приема (Protobuf): 2844 мс (20000 элементов) Время истечения для десериализации (Protobuf):141 мс (20000 элементов) Время истечения приема (сериализация данных): 7541 мс (20000 элементов)

для третьего

Время истечения приема (Protobuf): 2767 мс (20000 элементов) ВремяИстечение времени для десериализации (Protobuf): 145 мс (20000 элементов) Время истечения для приема (сериализация Datacontract): 3989 мс (20000 элементов)

После активации MTOM на 'Protobuf Transfert' это дает мне:

для первого вызова

Время для приема (Protobuf): 3316 мс (20000 элементов) Время для десериализации (Protobuf): 63 мс (20000 элементов) Время для приема (сериализация данных): 3769 мс(20000 элементов)

для второго вызова

Время истечения приема (Protobuf): 2279 мс (20000 элементов) Время истечения для десериализации (Protobuf): 57 мс (20000 элементов) Время истечения дляприем (сериализация данных): 3959 мс (20000 элементов)

Я добавляю эту часть кода для объектов размером

            long totoSize = new long();
        using (Stream s = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(s, totoList);
            totoSize = s.Length;
        }

        long titiSize = titiByte.Count();

iЯ дал мне 637780 с protobuf и 1038236 с DataContractSerializer. Длительность звонка лучше и стабильнее сегодня утром. Первый вызов protobuf = 2498 мс.1050 * третий вызов protobuf = 2498 мс datacontract = 5085 мс

1 Ответ

5 голосов
/ 26 апреля 2011

Некоторые факторы, влияющие на производительность:

  • подготовлен ли сериализатор ? Это автоматически при первом использовании для каждого типа; в первый раз, чтобы выяснить, как работает ваша модель, нужно провести немало проверок и т. д. Вы можете компенсировать это, вызывая Serializer.PrepareSerializer<YourType>() где-то во время запуска
    • или в качестве альтернативы, в v2 (доступно как «альфа») вы можете предварительно сгенерировать сериализатор как dll, если вам нужна максимально быстрая производительность при холодном запуске
  • что такое транспорт? в частности, для WCF вам необходимо помнить, как кодируется byte[] (это, конечно, не проблема для сокетов); Например, может ли транспорт использовать MTOM? или это кодировка base-64 byte[]?
    • и отметьте также, что вполне возможно, что Stream и byte[] обрабатываются по-разному; если вы можете измерить пропускную способность, вы можете попробовать оба
    • basic-http с включенным MTOM - мое предпочтение для транспортов WCF, если абсолютная скорость - ваша цель; или розетки, если вы хотите приблизиться к пределу
...