Sérialisation d’object rapide et compacte dans .NET

Je souhaite utiliser la sérialisation des objects pour communiquer sur le réseau entre un serveur Mono et des clients Silverlight. Il est très important que la sérialisation soit peu encombrante et rapide car le serveur va héberger plusieurs jeux en temps réel.

Quelle technique dois-je utiliser? BinaryFormatter ajoute beaucoup de surcharge aux classes sérialisées (version, culture, nom de classe, noms de propriété, etc.) qui ne sont pas nécessaires dans cette application.

Que puis-je faire pour rendre cet espace plus efficace?

Vous pouvez utiliser des tampons de protocole . Je change tout mon code de sérialisation de BinaryFormatter avec compression en Protocol Buffers et obtiens de très bons résultats. C’est plus efficace dans le temps et dans l’espace.

Il existe deux implémentations .NET par Jon Skeet et Marc Gravell .

Mise à jour : l’implémentation officielle de .NET peut être trouvée ici .

J’ai quelques points de référence pour les principaux sérialiseurs .NET disponibles basés sur le jeu de données Northwind.

Tests de sérialisation de .NET de Northwind

@marcgravell binary protobuf-net est l’implémentation la plus rapide, environ 7 fois plus rapide que le plus rapide des sérialiseurs Microsoft (le XML DataContractSerializer) dans la BCL.

Je maintiens également certains sérialiseurs de texte .NET haute performance open source:

  • JSV TypeSerializer est un format compact, propre, de type JSON + CSV, 3,1 fois plus rapide que le DataContractSerializer
  • ainsi qu’un JsonSerializer qui est 2,6 fois plus rapide.

En tant qu’auteur, je vous invite à essayer protobuf-net ; Il est livré avec des binarys pour Mono 2.0 et Silverlight 2.0, et est rapide et efficace . Si vous rencontrez des problèmes, envoyez-moi un e-mail (voir mon profil Stack Overflow); le support est gratuit.

La version de Jon (voir la réponse précédemment acceptée) est également très bonne, mais la version de protobuf-net de IMO est plus idiomatique pour C # – celle de Jon serait idéale si vous parliez de C # à Java.

J’ai eu un problème similaire, bien que j’utilise simplement .NET. Je voulais envoyer des données sur Internet aussi rapidement et facilement que possible. Je n’ai rien trouvé qui soit suffisamment optimisé, alors j’ai créé mon propre sérialiseur, nommé NetSerializer .

NetSerializer a ses limites, mais elles n’ont pas affecté mon cas d’utilisation. Et je n’ai pas fait de benchmark depuis un moment, mais c’était beaucoup plus rapide que tout ce que j’ai trouvé.

Je ne l’ai pas essayé sur Mono ou Silverlight. Je parie que cela fonctionne sur Mono, mais je ne suis pas sûr du niveau de support pour DynamicMethods sur Silverlight.

Vous pouvez transmettre les données via un DeflateStream ou GZipStream pour le compresser avant la transmission. Ces classes vivent dans l’espace de noms System.IO.Compression .

Vous pouvez essayer d’utiliser JSON. Ce n’est pas aussi efficace que les tampons de protocole, mais il serait beaucoup plus facile de surveiller les messages avec des outils tels que Wireshark, ce qui est très utile lors du débogage de problèmes. .NET 3.5 est fourni avec un sérialiseur JSON.

J’ai eu un problème très similaire – enregistrer dans un fichier. Mais ce qui suit peut également être utilisé sur un réseau tel qu’il a été conçu pour la communication à distance.

La solution consiste à utiliser la bibliothèque de Simon Hewitt – voir Optimisation de la sérialisation dans .NET – partie 2 .

La partie 1 de l’article indique (le gras est ma priorité): “… Si vous avez déjà utilisé .NET Remoting pour de grandes quantités de données, vous aurez constaté des problèmes d’évolutivité. Pour de petites quantités de données, Cela fonctionne assez bien, mais des quantités plus importantes consumnt beaucoup de ressources CPU et de mémoire, génèrent des quantités massives de données pour la transmission et peuvent échouer avec les exceptions Out Of Memory. des quantités de données peuvent le rendre impossible à utiliser dans les applications… ”

J’ai obtenu un résultat similaire pour mon application particulière, 40 fois plus rapide et 20 fois plus rapide (de quelques minutes à quelques secondes). La taille des données sérialisées était également très réduite. Je ne me souviens pas exactement, mais c’était au moins 2-3 fois.

Il est assez facile de commencer. Cependant, il existe un piège: n’utilisez que la sérialisation .NET pour la structure de données de très haut niveau (pour démarrer la sérialisation / désérialisation), puis appelez les fonctions de sérialisation / désérialisation directement pour les champs de la plus haute structure de données. Sinon, il n’y aura pas d’accélération … Par exemple, si une structure de données particulière (disons Generic.List ) n’est pas prise en charge par la bibliothèque, la sérialisation .NET sera utilisée à la place, ce qui est un no-no. Au lieu de cela, sérialisez la liste en code client (ou similaire). Pour un exemple, voir à proximité “” Ceci est notre propre encodage “. dans la même fonction que ci-dessous.

Pour référence: code de mon application – voir à proximité “Note: c’est le seul endroit où nous utilisons le .NET intégré …”.

Vous pouvez essayer BOIS, qui se concentre sur la taille des données compressées et fournit le meilleur conditionnement à ce jour. (Je n’ai pas encore vu d’optimisation.)

https://github.com/salarcode/Bois