lundi 15 juin 2009

Développer son MMORPG - Communications client serveur

Le combat épique, le duel au sommet: binaire ou XML? AdH a beaucoup changé non seulement sur ce choix de base, mais également sur la manière de l'implémenter.

Récapitulons:


  • Performances: Le binaire est le grand vainqueur. Difficile de faire mieux, puisqu'il n'y a généralement aucune transformation entre les données internes du programme et les données envoyées sur le fil. De son côté, XML devra transformer toutes les données en texte et rajouter des balises un peu partout, et ça prend du temps.

  • Taille: Le XML est généralement plus gros, mais l'on peut parfois avoir des surprises! Par exemple, un petit entier au format texte prendra moins de place qu'en binaire. Comparez: <l>1,2,1,1,1,2,5,2,1,2</l> fait 27 octets, mais passer ces 10 entiers 32 bits en binaire prendrait 40 octets! Certes, les puristes me feront remarquer que séparer les entiers par des virgules n'est pas franchement du XML. Et enfin, compressez!

  • Compatibilité Voilà un sujet dans lequel le XML est roi. Ce n'est que du texte, dans un encodage défini dans le message, il est très difficile de se tromper. Alors qu'en binaire, l'on va devoir parler de grand endian contre petit endian, de taille des types de base, de conventions pour passer la taille d'une chaine ou d'un tableau. Et si ça marche bien chez vous, qui sait ce que ça donnera quand vous enverrez le message à un Mac 64 bits?

  • Lisibilité: Le XML est le gagnant toutes catégories. On dira ce que l'on voudra sur la lecture de gros fichiers XML, mais c'est quand même mieux que de regarder des colonnes d'hexadécimal.

  • Maintenance: C'est sur ce point capital qu'avoir une bonne stratégie fera toute la différence, que ce soit en XML ou en binaire. Tout d'abord en XML: n'écrivez pas votre parseur, malheureux! N'écrivez pas non plus le code qui traduit les structures XML en structures de votre langage. Gé - Né - Rez. De nos jours, pléthore d'outils, tels Codesynthesis XSD et gSoap pour le C++, Microsoft XSD pour .NET, JAXB pour Java, et même mlxsd pour Ocaml (non, je déconne, n'utilisez surtout pas mlxsd pour quoi que ce soit de serieux!), vous font de belles classes qui savent se sérialiser toutes seules à partir d'un beau schéma. Changement de données? On change le schéma, on génère, on compile, on résout toutes les erreurs de compilation, on recompile (car seuls les cons pilent, ah ah!), et voilàte, ça marche! Et pour le binaire, alors? Attendez, on y arrive.


Par chance, comme pour la plupart des problèmes récurrents, il existe multitudes de frameworks qui vous les résoudront, tout en apportant une panoplie de difficultés nouvelles. Mais au moins, l'on ressent un certain soulagement à changer sa peine.

Blague à part, ICE, Corba, gsoap et beaucoup d'autres utilisent l'idée que les messages doivent être définis de manière centralisée via un langage de description, utilisé ensuite par des générateurs de code. Et ça, c'est un concept qui marche aussi bien en binaire qu'en XML. En plus, pour ceux qui auraient quand même décidé de coder le client et le serveur dans des langages différents, il suffit que le générateur de code puisse causer dans ces deux langages, et on est sortis d'affaire.

AdH a démarré sur du binaire, puis est passé au XML, revenu sur le binaire puis fait un dernier petit tour en XML avant de revenir fermement en binaire. N'ayant pas à supporter plusieurs langages, j'ai été faible, et j'ai décidé d'écrire moi-même mon générateur de code. L'avantage principale de mon approche est que je passe directement dans la description les types C++ supportés par mon sérializeur, ce qui veux dire que je peux passer des types très forts, tel mon AvatarId dans l'exemple du post en lien. Tous les autres frameworks m'auraient probablement obligé à passer un entier et perdre le typage, ou à décrire chaque type fort séparément, ce qui aurait sérieusement alourdi la chose.

En conclusion, choisir du XML ou du binaire a beaucoup moins d'importance que la manière dont on va maintenir et utiliser sa structure de messages. De plus en plus, il me semble indispensable d'avoir un bon framework qui pourra générer sans erreurs des brouettes de code ennuyeux. Choppez donc en un, et faites le bosser! Et si vous décidez de l'écrire vous-même, assurez vous que les fonctionnalités que vous rajoutez par rapport à un framework existant vous feront vraiment gagner du temps. Depuis, j'ai rajouté à mon générateur de code l'option de lier certains champs à la base de données, me permettant en quelques lignes de code d'extraire mon objet de la base et de l'envoyer sur le réseau!

Aucun commentaire: