Lorsque XNA Game Studio Express est sorti, je me suis dit que j'allais développer un jeu d'échecs pour Xbox 360. Comme les jeux d'échecs sur PC sont maintenant toujours constitués d'une interface graphique et d'un moteur indépendant, j'ai décidé de transposer en C# un des meilleurs programmes open source disponibles, Toga II 1.2.1A et de lui développer une interface utilisateur avec XNA Game Studio Express.

Voici le résultat :

Bon, ça n'a malgré tout pas été de tout repos, même si l'interface utilisateur est assez réduite. En effet, il a fallu commencer par transposer de C# en C++ les presque 400 Ko de source de Toga II ; bien que la syntaxe du C# soit assez proche de celle du C++, il subsiste des différences comme la quasi-impossibilité d'incorporer un tableau à l'intérieur d'une classe ou d'une structure (je parle bien du tableau lui-même qui est à l'intérieur de la structure et non d'une référence vers un tableau alloué séparément).

Après un portage "brut" de fonderie, j'ai été un peu surpris par les performances assez moyennes du résultat : sur mon portable, la version C++ de Toga II analyse environ 650 000 positions / seconde alors que la version transposée en C# n'atteint que 100 000 positions / seconde environ. Cela dit, il faut relativiser car ces 100 000 positions / seconde sont suffisantes pour exploser la plupart des joueurs humains.

L'enrobage du moteur a nécessité deux autres composants : la partie purement graphique et une petite bibliothèque de gestion de partie d'échecs (que j'ai portée à partir du code de CEBoard). Le plus long était comme souvent d'obtenir un rendu un peu agréable des pièces et des boîtes de dialogue (sans compter le dessin des boutons des pads xbox que j'ai dessinés avec Expression Design).

Une fois le jeu déposé sur Xbox... les performances étaient descendues à 950 positions / seconde environ !!!!

Heureusement, quelques emails échangés avec d'autres amateurs de XNA m'ont orienté vers la gestion de la mémoire : l'outil "XNA Framework Remote Performance Monitor for Xbox 360" est très pratique : il permet de voir en temps réel un certain nombre de compteurs de performance de XNA sur la Xbox et m'a permis de constater que j'avais environ 7 Garbage Collections par seconde... Or si on lit l'article http://blogs.msdn.com/netcfteam/archive/2006/12/22/managed-code-performance-on-xbox-360-for-xna-part-2-gc-and-tools.aspx, on voit que ma xbox passait son temps à faire le ménage !!!

Donc, voici les opérations que j'ai effectuées :

  • suppression de toutes les allocations dynamiques de l'interface utilisateur (conservation des objets entre les appels) et surtout du moteur de jeu : comme celui-ci est récursif, il était impossible de transformer toutes les variables locales en variables globales ! J'ai donc créé une liste par type d'objet alloué dynamiquement : lorsqu'on a besoin d'un objet, on prend la tête de liste (et effectue une allocation dynamique si la liste est vide) et surtout lorsqu'on n'en a plus besoin, on le remet dans la liste. C'est bien dommage de devoir gérer ainsi la mémoire en C# mais bon, ce n'est pas plus compliqué de penser à appeler delete en C++ !
  • remplacement des chaînes de caractères utilisées par le moteur pour envoyer ses informations à l'IHM (le moteur C++ original communique via son entrée standard et sa sortie standard) par une classe (allouée comme les précédentes).
  • changement de l'affinité du thread du moteur pour le mettre sur un processeur différent de l'interface homme machine.

Le gain est appréciable : on atteint maintenant 15 000 positions / seconde sur la xbox. C'est encore loin du PC et encore plus de la version C++ mais ce n'est pas très étonnant : non seulement, la xbox utilise le .NET Compact Framework et non le .NET Framework 2.0 qui est plus sophistiqué au niveau du runtime mais aussi XNA Express a été optimisé pour les opérations graphiques et non celles de calcul.

Un dernier point à noter avant les liens pour télécharger XNA Chess : dans la position initiale, le moteur C# sur mon portable générait initialement 3380 GC de génération 0 en 10 secondes (pour donc environ 1 000 000 positions analysées). La version "optimisée" descend à une trentaine... mais les performances sur le PC n'ont quasiment pas bougé (quelques % tout au plus) ! Cela montre à quel point le GC "générationnel" du .NET Framework (malheureusement absent de la version Compact) est efficace.

http://alain.zanchetta.free.fr/softs/XnaChess-Windows.ccgame

http://alain.zanchetta.free.fr/softs/XnaChess360-Xbox360.ccgame

Source C# de Toga