Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    N'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

Comparaison de performance des sérialiseur XML .net (DataContractSerializer, XmlSerializer, SoapFormatter)

Il est fréquent que l’on veuille transformer un objet .net dans un format XML afin de le sauvegarder sur le disque dur, en base, etc. Cette opération correspond à la sérialisation XML.

Un sérialiseur est une classe .net permettant de faire cette opération de sérialisation. A partir de .net 3.5 SP1, .net fourni 3 sérialiseurs différents : XmlSerializer, SoapFormatter, DataContractSerializer.

Ces 3 sérialiseurs ont chacun leurs avantages et inconvénients. J’ai décidé aujourd’hui de m’intéresser aux performances de ces sérialiseurs. Les performances que je mesure ici sont le temps d’exécution, je ne mesure pas la consommation mémoire, l’éventuelle parallélisassion, la taille du fichier générée, etc. De plus, je ne prends pas en compte les spécificités de chacun des sérialiseurs, je me situe dans un cas d’utilisation très basique.

Environnement de test

Les tests ont été exécutés sur mon laptop (Win 7 enterprise, 8Go de ram, 8 coeur), en mode de compilation release, any CPU avec .net 4.0. Les temps de réponses affichés sont exprimés en millisecondes et correspondent à une moyenne d’au moins 3 exécutions.

J’ai également ajouté une comparaison en utilisant le BinaryFormatter, le sérialiseur qui transforme les données au format binaire.

J’ai effectué mes tests avec 3 types différents :

Type simple :

[Serializable] // required for soapformatter
public class A
{
    public int MyProperty { get; set; }
    public int MyProperty2 { get; set; }
}

Type intermediaire :

[Serializable] // required for soapformatter
public class B
{
    public int MyProperty { get; set; }
    public int MyProperty2 { get; set; }
    public String MyProperty3 { get; set; }
    public DateTime MyProperty4 { get; set; }
    public A MyPropertyA1 { get; set; }
    public A MyPropertyA2 { get; set; }
}

Type complexe :

[Serializable] // required for soapformatter
public class C
{
    public int MyProperty { get; set; }
    public int MyProperty2 { get; set; }
    public int MyProperty3 { get; set; }

    public A MyPropertyA1 { get; set; }
    public A MyPropertyA2 { get; set; }

    public B MyPropertyB1 { get; set; }
    public B MyPropertyB2 { get; set; }
}

A chaque sérialisation, je créé une nouvelle instance de ces objets, le code utilisé est le suivant :

static A GetA()
{
    return new A()
    {
        MyProperty = 1,
        MyProperty2 = 2
    };
}
static B GetB()
{
    return new B()
    {
        MyProperty = 1,
        MyProperty2 = 2,
        MyProperty3 = "3",
        MyProperty4 = DateTime.Now, 
        MyPropertyA1 = GetA(),
        MyPropertyA2 = GetA()
    };
}
static C GetC()
{
    return new C()
    {
        MyProperty = 1,
        MyProperty2 = 2,
        MyProperty3 = 3,
        MyPropertyA1 = GetA(),
        MyPropertyA2 = GetA(),
        MyPropertyB1 = GetB(),
        MyPropertyB2 = GetB()
    };
}

Enfin, le code utilisé pour l’exécution des tests est le suivant :

Serialisation :

Stopwatch watcher = Stopwatch.StartNew();

// SoapFormatter serializer = new SoapFormatter();
for (int i = 0; i < 10000; i++)
{
    SoapFormatter serializer = new SoapFormatter();
    using (MemoryStream ms = new MemoryStream())
    {
        B b = GetB(); 
        serializer.Serialize(ms, b);
    }
    if (i == 0)
    {
        Console.WriteLine(watcher.ElapsedMilliseconds);
    }
}
Console.WriteLine(watcher.ElapsedMilliseconds);

Déserialisation :

using (MemoryStream ms = new MemoryStream())
{
    var o = GetA();
    var innerSerializer = new DataContractSerializer(typeof(A));
    innerSerializer.WriteObject(ms, o);


    while (true)
    {
        Stopwatch watcher = Stopwatch.StartNew();

        var serializer = new DataContractSerializer(typeof(A));
        for (int i = 0; i < 10000; i++)
        {
            //var serializer = new DataContractSerializer(typeof(A));
            using (MemoryStream ms2 = new MemoryStream())
            {
                ms.Position = 0; 
                ms.CopyTo(ms2);
                ms2.Position = 0; 
                serializer.ReadObject(ms2);
            }
            if (i == 0)
            {
                Console.WriteLine(watcher.ElapsedMilliseconds);
            }
        }
        Console.WriteLine(watcher.ElapsedMilliseconds);
        Console.ReadLine();
    }
}

Les tests ont été réalisés selon deux modes, soit en instanciant à chaque fois un sérialiseur, soit en mutualisant le sérialiseur pour les 10 000 itérations.

Je différencie également le temps d’exécution de la première sérialisation des 9 999 suivants.

Résultat de test

Les résultats ci-dessous sont exprimés en millisecondes.

Sérialisation

Résultats lorsque l’on instancie un nouveau sérialiseur à chaque itération :

image

Résultat lorsque l’on mutualise l’instance du sérialiseur pour les 10 000 itérations :

image

Constat :

La première chose que l’on peut remarquer est qu’à part pour le XmlSerializer, il y a peu de différence entre la réutilisation ou non du sérialiseur. Dans le cas du XmlSerializer, on voit que réutiliser le type permet de meilleure performance. A noter que le XmlSerializer est Thread Safe il peut donc être stockée dans une variable static et mutualiser entre différents threads.

On voit ensuite que le XmlSerializer est le plus long pour des objets simples, dès que les objets deviennent plus complexes, le SoapFormatter devient de plus en plus lent.

Les sérialiseurs les plus rapides sont les BinaryFormatter et DataContractSerializer. Le BinaryFormatter est rapide dès la première exécution alors que le DataContractSerializer est un peu plus lent au démarrage, il devient ensuite plus rapide lorsque l’on effectue plusieurs sérialisations.

Déserialisation

Résultat lorsque l’on instancie un nouveau sérialiseur à chaque itération :

image

Résultat lorsque l’on mutualise l’instance du sérialiseur pour les 10 000 itérations :

image

Constat :

Comme lors de la sérialisation, on constate que l’initialisation du XmlSerializer est assez couteux, une fois de plus il est préférable de mutualiser l’instance du XmlSerializer.

Pour les types complexes, à part avec le SoapFormatter, la déserialisation prend à peu près le même temps. Pour les types simples, le BinaryFormatter reste le plus rapide.

Conclusion

Ces résultats nous amène aux conclusions suivantes :

  • Pour la déserialisation, le BinaryFormatter est le plus rapide suivi de très près par la DataContractSerializer
  • Pour la sérialisation,
    • pour des types complexe, le DataContractSerializer est le plus rapide
    • pour des types simple, le BinaryFormatter est le plus rapide
  • Si l’on utilise le XmlSerializer, il est préférable de conserver l’instance dans une variable static.
  • Le SoapFormatter est le serialiseur le plus lent

Attention, il ne faut pas oublier que chaque sérialiseur a ses propres spécificités. Lors du choix d’un sérialiseur, la performance n’est pas le seul critère à prendre en compte. De plus, je ne mesure pas le temps d’exécution lorsque l’on utilise ces spécificités.

Et vous, avez-vous constaté des différences de performance entre les différents sérialiseur ?

Posted: samedi 2 juillet 2011 14:17 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

richardc a dit :

DataContractSerializer est, à ma connaissance, le sérialisateur recommandé par MS.

Mais as tu testé protobut-net ? http://code.google.com/p/protobuf-net/

# juillet 2, 2011 16:21

cyril a dit :

Richard, je ne suis pas sur que DataContractSerializer soit LA solution recommandé par Microsoft. Cela dépend des contextes. Si tu souhaites parfaitement maitrisé le schéma de ton XML, alors, tu vas utiliser le XmlSerializer qui permet de mettre ces propriétés sous la forme d'attribut, si tu souhaites de la souplesse quand au versionning de tes contrats, tu utilises le DataContractSerializer. Quand au SoapFormatter, euh ... je sèche

Par rapport à protobuf.net. Je viens de faire rapidement le test de déserialisation de l'objet complexe avec protobuf et pour 10 000 objets, cela prend environ 80ms, soit 5 fois plus rapide que la déserialisation binaire classique.

Cela semble donc être quelque chose d'interessant lorsque le format XML n'est pas un prérequis (ce qui arrive)

# juillet 2, 2011 18:41
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- L’application des MiniDrones Parrot est aussi disponible pour Windows 8.1 par Blog de Jérémy Jeanson le 10-28-2014, 15:01

- L’application des MiniDrones Parrot est enfin disponible pour Windows Phone par Blog de Jérémy Jeanson le 10-27-2014, 09:49

- Mise à jour Samsung 840 EVO sur core server par Blog de Jérémy Jeanson le 10-27-2014, 05:59

- MVP Award 2014 ;) par Blog de Jérémy Jeanson le 10-27-2014, 05:42

- « Naviguer vers le haut » dans une librairie SharePoint par Blog de Jérémy Jeanson le 10-07-2014, 13:21

- PowerShell: Comment mixer NAGIOS et PowerShell pour le monitoring applicatif par Blog Technique de Romelard Fabrice le 10-07-2014, 11:43

- ReBUILD 2014 : les présentations par Le blog de Patrick [MVP Office 365] le 10-06-2014, 09:15

- II6 Management Compatibility présente dans Windows Server Technical Preview avec IIS8 par Blog de Jérémy Jeanson le 10-05-2014, 17:37

- Soft Restart sur Windows Server Technical Preview par Blog de Jérémy Jeanson le 10-03-2014, 19:43

- Non, le certificat public du CA n’est pas un certificat client !!! par Blog de Jérémy Jeanson le 10-03-2014, 00:08