Bonjour ! Je m’appelle Robert Neckorcuk, responsable de l’équipe de plate-forme chez ArenaNet. Aujourd’hui, je vais être le porte-parole d’un grand effort pluridisciplinaire qui a géré l’événement bêta des spécialisations d’élite de Guild Wars 2®: Visions of Eternity™, depuis sa publication, lors des problèmes qui en ont découlé, et jusqu’à leur résolution. Les événements bêta servent en général à fournir des retours aux équipes de développement concernant les nouveaux systèmes, fonctionnalités et compétences. Mais comme nous l’avons récemment vécu, ces bêtas sont également le premier essai live des nouvelles technologies qui permettent de concrétiser ces nouveaux systèmes, fonctionnalités, et compétences. Cet article va revenir en détail sur le lancement difficile de cet événement bêta, tout en vous révélant comment notre équipe a pu relever ces défis, grâce à votre aide !
Je voudrais commencer par remercier l’ensemble de la communauté : nous sommes conscients que la situation vécue était loin d’être idéale, depuis les premiers problèmes rencontrés en jeu jusqu’à notre demande d’aide pour récolter des données, alors que nous venions de publier un événement qui occasionnait des plantages. Tout au long de l’événement, nous avons pu lire de nombreux messages de compréhension et de soutien. Notre équipe n’a pas les mots suffisants pour exprimer toute sa gratitude suite à la résolution de cette situation. Merci à tous.
La bêta « alpha »
Le mercredi 20 août, à précisément 18h17, heure de Paris (9h17, heure du Pacifique), le week-end d’événement bêta visant à présenter les nouvelles spécialisations d’élite de notre sixième extension, Guild Wars 2: Visions of Eternity, a commencé. Ce début était déjà décevant, puisque la bêta était censée commencer à 18h ! Suite à une erreur liée au fuseau horaire, l’horaire de lancement s’est retrouvé décalé d’une heure. Heureusement, nous avons pu modifier des fichiers de configuration et faire en sorte que l’événement bêta commence avant 19h !
Si la présence de bugs n’est jamais planifiée, nous avons néanmoins des mesures en place pour nous permettre de réagir rapidement en cas de problème. Peu après la publication, nous avons identifié trois problèmes qu’il nous a fallu corriger aussi vite que possible. Nous avons pu en neutraliser un grâce à des fichiers de configuration. Un deuxième problème, sans lien avec l’événement bêta, a pu être réglé en déployant une modification vers un de nos serveurs de développement. Le troisième problème nécessitait une mise à jour du jeu le jour même. D’ici 23h, les trois problèmes avaient été gérés, et nous étions impatients à l’idée de nous détendre et de profiter de la bêta. Mais peu après, notre responsable communauté a envoyé un message au groupe pour demander ce qu’il se passait, car le jeu était en plein chaos…
Partout depuis nos postes en télétravail, nous avons froncé les sourcils. Nous ne recevions aucun signalement de plantage, et tous les graphiques étaient stables. Ce n’est qu’en commençant à creuser la question que nous avons découvert la cause du problème : un de nos signalements d’erreur client indiquait sans cesse un « Code 1083 »… (musique inquiétante)
Le grand blocage
Le code 1083 est un message d’erreur très spécifique, référencé une seule fois dans toute notre base de code de serveur : « En attente de déblocage ». Dans l’architecture serveur de Guild Wars 2, les « blocages » sont un composant de l’organisation de nos contextes de carte, car celles-ci peuvent être créées sur n’importe quel serveur de notre système d’hébergement. Le mécanisme de blocage de personnage est conçu pour garantir qu’un seul contexte de carte à la fois a l’autorité suffisante pour écrire des données sur votre personnage. C’est un outil utile pour éviter les exploitations de bug, mais il sert aussi à assurer la cohérence entre les données du personnage et celles de votre compte. En temps normal, quand vous entrez dans une carte, un blocage temporaire est placé sur la base de données de votre personnage, indiquant que le serveur de jeu souhaite recevoir cette autorité. Une passation d’autorité se produit quand il n’y a pas de blocage actuel, ou quand un blocage actuel est libéré par un serveur de jeu précédent ; le blocage temporaire est alors converti en blocage d’autorité.
Mais nous ne vivons pas dans un monde parfait : les bugs existent, et les cartes sont susceptibles de planter. En tant que développeurs, nous tenons à rassembler autant d’informations de débogage que possible sur ces événements. C’est pourquoi, quand un contexte de carte plante, nous pouvons faire une courte pause pendant l’arrêt, rassembler des informations pertinentes, puis les envoyer par e-mail au bureau afin de mener l’enquête et de corriger le problème. Durant ce processus, le serveur de jeu sait que la carte a planté, et il peut dire à la base de données de libérer les éventuels blocages actuels.
À ce stade, nous avons trouvé notre premier véritable indice menant à la cause de notre absence de visibilité opérationnelle et du type d’erreur qu’il nous fallait traquer. Comme nous ne recevions aucun signalement de ces plantages, nous savions que cette partie de code « nettoyage » n’était jamais activée, ce qui signifiait que les blocages n’étaient pas libérés correctement. Le contexte de carte qui maintenait ce blocage n’existait plus, et il n’y avait donc plus d’entité à laquelle dire de libérer le blocage. L’ultime solution était de simplement mettre fin au blocage après un certain temps. Au bout d’un certain temps, sans mise à jour du précédent propriétaire du blocage, il nous fallait libérer le blocage, afin de permettre au personnage de se reconnecter à un contexte de carte pouvant alors obtenir un nouveau blocage.
Ce long délai sert à prévenir un certain nombre d’interruptions d’infrastructure. Nous savons qu’il est pénible de ne pas pouvoir se connecter au jeu, mais il s’agit d’un moindre mal, car cela garantit l’intégrité et la cohérence des données de nos joueurs.
Après en avoir discuté au sein de l’équipe et avec nos responsables, nous avons estimé que le problème était trop conséquent et qu’il serait préférable de mettre un terme prématuré à l’événement bêta, afin d’offrir une meilleure expérience aux joueurs et de permettre à notre équipe d’examiner la source du problème. Sachant que notre code d’application plantait et n’activait pas les processus de collecte et de signalement, notre rasoir d’Occam nous indiquait qu’il nous fallait chercher un problème de corruption de mémoire… Plus tard dans la nuit, les documents du système d’exploitation ont confirmé cela.
Une aiguille dans un tas d’aiguilles
Nous avons commencé par décomposer le problème pour essayer de trouver le plus petit aspect où celui-ci se produisait. Cela allait nous éviter de devoir chercher à travers des millions de lignes de code, mais vu ce que nous savions, nous ne pouvions pas affiner énormément notre recherche. Parmi les neuf nouvelles spécialisations d’élite, nous ne savions pas quelle profession était le « catalyseur » (littéralement) du plantage.
Nous publions constamment du code, et même si l’événement bêta s’est déroulé en août, les tout premiers changements du code accompagnant les nouvelles spécialisations remontent à l’année dernière. Le jeudi, plusieurs membres de l’équipe ont commencé à s’attaquer au problème en cherchant des mots-clés dans les commentaires de publication et en explorant les modifications.
D’autres personnes ont fouillé les données pour voir s’il était possible d’identifier des logiques concernant certaines cartes, les professions sur ces cartes, les nombres de joueurs sur les cartes, etc., afin de nous aider à affiner davantage notre recherche.
Nous avions une piste supplémentaire qui nous a aidés à préciser nos recherches : la manière selon laquelle nos serveurs de jeu gèrent et organisent les différents types de mémoire.
L’esprit d’un serveur de jeu
Tous les jeux ont besoin de différentes données pour pouvoir opérer : à quel endroit faire apparaître telle ou telle créature, à quel moment activer les événements dynamiques, la géométrie du sol pour détecter les collisions, et bien plus encore. Un serveur de jeu peut créer un certain nombre de contextes de carte, dont chacun récupérera de la mémoire pour stocker ses informations locales afin de les exploiter et de les mettre à jour.
En vue de minimiser notre empreinte mémoire et d’éviter les doublons, nos serveurs de jeu créent également une section de mémoire statique partagée. Nous pouvons y placer les données qui ne changent pas et les mettons en lecture seule, partagées entre tous les contextes de carte. La majorité des éléments liés aux identifiants – dont les objets, les succès et les types de créatures – est stockée ici et peut être lue par n’importe quel contexte de carte, l’information restant la même, quelle que soit la carte gérée.
D’après les plantages de corruption de mémoire que nous avons observés (ou non), nous avons pu déterminer que l’unique cause possible était un problème de mémoire partagée. Nous avions enfin affiné notre recherche.
S’obstiner, sans relâche
Le jeudi, tandis que nous poursuivions nos investigations, nous avons demandé à l’ensemble de l’équipe de tester le jeu pour essayer de reproduire le plantage sur l’un de nos serveurs de développement. Nos instructions étaient volontairement floues : créer un personnage de bêta, appuyer à la suite sur différentes touches, et envoyer un rapport en cas de plantage… Il n’y en a eu aucun.
Nous n’arrivions pas à provoquer le moindre plantage.
Nos serveurs de développement utilisent un code et une configuration légèrement différents de ceux de nos serveurs live. Le vendredi, nous avons appliqué un autre plan afin de tester en interne le jeu sur nos clients de simulation – notre outil qui ressemble le plus à un environnement live.
Là non plus, nous n’avons pas réussi à provoquer de plantage.
L’unique option qui nous restait était de réactiver l’événement bêta pour le jeu live, en espérant que nos joueurs provoqueraient eux-mêmes un plantage du serveur.
La bêta « bêta »
À 21h pile, l’événement bêta était réactivé. Pendant plusieurs minutes, le silence a régné dans notre canal de discussion, tandis que nous réfléchissions à ce qui pourrait se passer. Nous avions apporté quelques modifications supplémentaires avant de réactiver l’événement bêta, en identifiant certains outils et agents de surveillance pour avoir le plus de chances possible de repérer les plantages et de capturer des données de débogage… mais nous ne nous étions pas préparés à avoir autant de chance que ça !
Tout juste avant la réactivation de 21h, nous avons déployé une nouvelle version pour corriger un problème concernant les nouvelles invocations des joueurs. Notre première aubaine a été que cette version a forcé l’ensemble de nos serveurs de jeu à créer de nouveaux tampons de mémoire partagée, ce qui a modifié tous les emplacements de mémoire. À 21h11, nos outils de surveillance ont signalé le premier plantage. Notre deuxième coup de chance est arrivé peu après, quand nous avons reçu un rapport de plantage complet venant de nos diagnostics internes. Un autre coup de chance était la nature du plantage, déterminé par le fichier de plantage : un bout de code tentait de supprimer un morceau de mémoire déjà supprimé.
« Quel est le sens de cette double suppression ? » nous sommes-nous demandés. « Et puis, pourquoi supprimer des éléments de la mémoire en lecture seule ? »
Tout d’abord, nous voulions nous assurer que ce plantage était bien celui que nous cherchions, et pas seulement une coïncidence fortuite. Nous avons transmis les informations de l’enquête sur le plantage à notre équipe d’assurance-qualité, et quinze minutes plus tard, nous avons pu reproduire le problème. Dans l’intervalle, notre équipe qui surveillait le jeu live avait remarqué plusieurs autres plantages : certains envoyaient des rapports de plantage, tandis que d’autres activaient les outils de surveillance de mémoire que nous avions installés auparavant. Les rapports faisaient tous mention d’une tentative de lecture ou de suppression d’une section de mémoire déjà effacée. Après une dernière discussion pour confirmer si nous avions rassemblé toutes les informations requises, nous avons à nouveau désactivé l’événement bêta.
Le problème des ingénieurs et sa correction
La nouvelle spécialisation d’élite de la profession des ingénieurs, les amalgames, a introduit une nouvelle mécanique de profession notable nommée « Transformation », ainsi qu’un nouveau chemin de code sur la manière dont ces compétences sont définies et mises à jour. C’est ce nouveau comportement qui a transformé nos projets d’une bêta triomphante en une épreuve de trois jours.
Le problème s’est produit en raison d’une confusion concernant une structure de données qui utilisait de la mémoire de contexte de carte locale, c’est-à-dire la mémoire partagée du serveur de jeu. Quand un joueur ingénieur ayant équipé la spécialisation d’élite amalgame changeait une compétence de transformation qui n’était pas encore rechargée, le code cherchait à stocker ce changement de compétence et le reste du temps de recharge associé au contexte du joueur. Ce changement s’effectuait à l’aide d’un pointeur qui faisait par mégarde référence à la mémoire partagée. Ainsi, alors que nous souhaitions supprimer une référence locale à la compétence précédente, nous supprimions en fait la compétence de la mémoire partagée. La fois suivante qu’un joueur du même serveur de jeu cherchait à référencer la compétence de transformation désormais supprimée, un plantage survenait.
Heureusement pour nous, nous avions écrit cette structure de données et ses fonctions associées, et il nous a suffi d’une ligne de code pour corriger le problème.
À 21h53, nous avons envoyé ce correctif à notre branche de développement, puis nous avons commencé les processus de détection de bugs, de tests de régression et de publication du changement vers nos versions de mise en scène, et enfin vers les serveurs live.
Pour ma part, je suis encore surpris par la rapidité avec laquelle nous sommes à même de publier de telles modifications. C’est en partie grâce à la magie de notre équipe d’ingénierie, et à « E », qui a corrigé ce problème spécifique. Néanmoins, notre processus de publication a plus d’un tour dans son sac pour nous aider à faire rapidement progresser les choses. Pour la majorité des mises à jour du mardi, nous devons exécuter une publication complète qui comprend tout notre code et notre contenu. Mais pour une modification concernant un seul fragment de code de serveur, nous avons pu utiliser une publication rapide. Il s’agit d’une mise à jour beaucoup plus restreinte, qui prend peu de temps à mener, ce qui nous a permis de la rendre disponible très rapidement.
La bêta « gamma »
Quelques heures plus tard, quand le correctif a été déployé dans le jeu live, nous avons à nouveau activé l’événement bêta. Les membres de nos équipes d’ingénierie et d’assurance-qualité se sont connectés pour créer des personnages amalgames et ont vérifié le correctif. À notre grand soulagement, aucun plantage ne s’est produit durant cette vérification.
Notre équipe a continué de surveiller la situation, en utilisant les mêmes outils que plus tôt dans la journée, et le correctif avait manifestement joué son rôle. Nous étions ravis de pouvoir enfin proposer ces nouvelles spécialisations d’élite à nos joueurs, avec toutes les nouvelles compétences et mécaniques fonctionnant comme prévu.
En conclusion
Après cet incident, et après la clôture de l’événement bêta une semaine plus tard, l’équipe s’est à nouveau rassemblée pour récapituler, itérer et planifier. Est-il possible de repérer les problèmes de ce type en interne et plus tôt lors du processus ? Existe-t-il un nouvel outil ou une procédure qui aiderait à limiter ce type de problème ? Si un problème similaire venait à se représenter, que ferions-nous de différent ? Comment aurions-nous pu rétablir plus rapidement une version jouable ?
Je vais reprendre une conclusion que j’avais écrite pour un autre article en 2020 :
Nos efforts continus visent toujours à offrir à nos joueurs la meilleure expérience et la meilleure ergonomie pour nos services. Nous tenons à rendre hommage aux designs conçus par nos prédécesseurs, ainsi qu’aux outils et aux procédés que nous utilisons pour assurer une qualité et des mécaniques et événements en jeu de classe mondiale. Même si nous n’atteindrons peut-être jamais la perfection, nous nous efforcerons de le faire avec chaque procédure et déploiement futurs. Alors que nous attendons avec impatience les nouvelles fonctionnalités et les nouveaux projets que les équipes de conception et de jeu vous préparent, nous travaillons en permanence dans les coulisses pour nous assurer que vous puissiez toujours profiter de tout ce que Guild Wars 2 vous réserve.
Merci encore et à bientôt en Tyrie !


