Resolución de la serie de problemas con la beta de especializaciones de élite

por El equipo de Guild Wars 2 el 17 de octubre de 2025

¡Hola! Soy Robert Neckorcuk, jefe del equipo de plataformas, y hoy me toca contaros el enorme esfuerzo multidisciplinario que requirió la gestión del evento beta de especializaciones de élite de Guild Wars 2®: Visions of Eternity™, desde su lanzamiento hasta la resolución de los problemas que surgieron. Para los eventos beta, los equipos de desarrollo suelen recabar comentarios sobre las nuevas funciones, habilidades y sistemas; pero como pudimos comprobar recientemente, estas betas también son la primera prueba real de las nuevas tecnologías que permiten crear esas funciones, habilidades y sistemas nuevos. En esta publicación os hablo desde una perspectiva interna de las dificultades iniciales y del modo en que nuestro equipo las abordó y las superó con vuestra ayuda.

Quiero empezar con un agradecimiento especial para toda la comunidad; sabemos que no fue la mejor de las situaciones. Empezando por el hecho de que los problemas iniciales del juego nos obligaron a pediros ayuda para recopilar datos sabiendo que habíamos habilitado a propósito un evento que podía provocar bloqueos. Durante todo el evento, recibimos numerosos mensajes de apoyo, empatía y comprensión. En nombre de todo el equipo, no hay palabras para expresaros nuestro agradecimiento por ello mientras nos esforzábamos en dar con una solución. Gracias a todos.

La beta “alfa”

El miércoles 20 de agosto, exactamente a las 18:17 hora peninsular española (09:17, hora del Pacífico), dio comienzo el evento beta para las nuevas especializaciones de élite de nuestra sexta expansión, Guild Wars 2: Visions of Eternity. ¡Ya empezamos mal, porque se suponía que debía comenzar a las 18:00! Nos liamos con la conversión de las zonas horarias, y la hora de inicio se retrasó una hora. ¡Por suerte, pudimos modificar algunos archivos de configuración y conseguimos que el evento comenzara antes de las 19:00!

Nunca pretendemos empezar con fallos, pero tenemos planes y sistemas preparados para reaccionar rápidamente en caso de que surjan. Al poco del lanzamiento, identificamos tres problemas que sabíamos que había que solucionar cuanto antes. Uno de ellos sencillamente lo desactivamos usando archivos de configuración. El segundo problema, sin relación con el evento beta, pudo arreglarse implementando un cambio en uno de nuestros servidores. Para el tercero se necesitaba una versión del juego de ese mismo día. A las 23:00, ya estaban solventados los tres problemas y nos disponíamos a relajarnos y pasarlo bien con el evento beta. Poco después, la persona responsable de la comunidad envió un mensaje al grupo pidiendo una actualización del estado, ya que el juego hacía agua.

En nuestros puestos remotos todo se volvieron caras largas. No estábamos recibiendo informes de bloqueos y todos los gráficos parecían estables. Pero cuando averiguamos por dónde empezar a investigar, dimos con el problema. En uno de los informes de errores del cliente aparecía constantemente un código 1083. Suena música inquietante…

Captura de pantalla del error de red 1083.

Todo bloqueado

El código 1083 es un error bastante particular que solo aparece una vez en todo el código de nuestro servidor con este mensaje: “Waiting for Unlock” (esperando al desbloqueo). En la arquitectura central del servidor de Guild Wars 2, los “locks” (bloqueos) son una parte fundamental de la organización de los contextos de los mapas, ya que estos pueden crearse en cualquier servidor dentro de nuestra red de alojamiento. El mecanismo de bloqueo de personajes se encarga de que solo haya un contexto de mapa con permiso para editar datos en el registro de un personaje. Es una herramienta muy útil para prevenir fallos aprovechables, pero sobre todo sirve para garantizar la consistencia en los datos de los personajes y las cuentas. Cuando entráis en un mapa, normalmente el juego deja pendiente en la base de datos un bloqueo temporal para vuestro personaje, lo que indica que ese servidor está intentando asumir la autoridad. Cuando no hay un bloqueo existente o el anterior desaparece de un servidor del juego previo, se produce una transferencia y el bloqueo pendiente pasa a ser bloqueo de autoridad.

Pero no siempre sale todo a pedir de boca; los fallos se producen y los mapas se bloquean. Como desarrolladores, queríamos recopilar toda la información posible sobre estos eventos para hacer una depuración. Cuando un mapa de contexto se bloquea, podemos hacer una breve pausa durante el proceso de apagado, recopilar la información relevante, y enviársela por correo electrónico al equipo de la oficina para que lo investiguen y lo arreglen. Mientras tanto, el servidor sabe que ese mapa se está bloqueando y puede decirle a la base de datos que elimine los bloqueos activos.

Ahí obtuvimos la primera pista de verdad sobre la causa de la falta de visibilidad operativa y el tipo de error que teníamos que rastrear. Como no estábamos recibiendo informes sobre los fallos, nos dimos cuenta de que la ruta de código de “limpieza” nunca se activaba, lo que significaba que los bloqueos no se liberaban de forma limpia. El contexto de mapa que contenía ese bloqueo ya no existía, así que no había ninguna entidad que dijera que había que liberarlo. La solución definitiva consistía simplemente en hacer caducar el bloqueo en un temporizador. Al cabo de un rato, sin una actualización del anterior propietario del bloqueo, lo liberaríamos y el personaje podría volver a conectarse a un contexto de mapa capaz de adquirir un bloqueo nuevo.

El temporizador largo está ahí para cubrir diversas interrupciones en la infraestructura. Sabemos lo frustrante que es no poder iniciar sesión, pero es el menor de los males, ya que eso garantiza la integridad y consistencia de vuestros datos.

Tras debatirlo entre el equipo y la dirección, decidimos que este era un asunto serio y que lo mejor sería finalizar el evento beta antes de tiempo para ofreceros una mejor experiencia y poder investigar el origen del problema. Con la evidencia de que el código de la aplicación se bloqueaba sin activar los flujos de recopilación y envío, aplicamos el principio de la navaja de Ockham: decidimos que lo más probable era que se tratara de un problema de corrupción de memoria. Esto quedó confirmado más tarde mediante los registros del sistema operativo.

Una aguja en un pajar

Comenzamos por analizar el problema e intentar acotar al máximo el área donde podía estar el error. Así nos evitábamos tener que revisar millones de líneas de código, aunque con la información que teníamos no podíamos reducir demasiado el rango de búsqueda. Teníamos nueve especializaciones de élite nuevas, y no sabíamos qué profesión era la catalizadora (va con segundas) del bloqueo.

Publicamos código constantemente, y aunque el evento beta fue en agosto, los primeros cambios necesarios para dar soporte a estas nuevas especializaciones los realizamos el año pasado. El jueves, varios miembros del equipo empezaron a investigar el problema desde este ángulo, buscando palabras clave en los comentarios de los commits y revisando los cambios.

Otros compañeros analizaron los datos para ver si podían detectar patrones en ciertos mapas, en profesiones o cuentas de jugadores de esos mapas, etc. Con eso intentaban acotar aún más el problema.

Teníamos otra pista que nos ayudó a centrar la búsqueda, y es el modo en que nuestros servidores del juego administran y agrupan los distintos tipos de memoria.

La mente de un servidor de juego

Cualquier juego necesita datos para saber cómo tiene que funcionar: qué criatura aparece y dónde, cuándo se activan eventos dinámicos, la geometría del suelo para detectar colisiones, y muchas más cosas. Un servidor de juego es capaz de crear cierto número de contextos de mapa, y cada uno de ellos exige su porción de memoria para albergar toda su información local para el uso y las actualizaciones.

Con el fin de reducir el consumo de memoria y evitar la duplicación de datos, nuestros servidores del juego también crean una sección de memoria estática compartida. En esa sección colocamos los datos que no cambian y los marcamos como de solo lectura, y a ellos pueden acceder todos los contextos de mapa. La mayoría de los elementos asociados a etiquetas, como objetos, logros o tipos de criaturas, están ahí. Cualquier contexto de mapa los puede leer, ya que la información es siempre la misma, independientemente del mapa que se esté ejecutando.

A juzgar por los bloqueos por corrupción de memoria que vimos (o no vimos), llegamos a la conclusión de que la única causa posible era un problema con la memoria compartida. Eso estrechó un poco más el campo de búsqueda.

Gráfico que indica los momentos en que el servidor del juego muestra datos estáticos y cuándo no los muestra.

Un intento tras otro

Mientras investigábamos, aprovechamos que el jueves estaba prevista una prueba de juego interna de todo el equipo para intentar reproducir el bloqueo en uno de nuestros servidores de desarrollo. Le dimos unas instrucciones deliberadamente ambiguas: crear un personaje en la beta, apretar botones sin parar, y enviar un informe si se producía un bloqueo. No hubo bloqueos.

No éramos capaces de provocar un bloqueo.

El código y la configuración de nuestros servidores de desarrollo difieren ligeramente de los del juego en vivo. El viernes, se nos ocurrió un plan para ejecutar otra prueba interna en nuestros clientes del entorno de pruebas, que es lo que más se parece al entorno en vivo.

Tampoco así pudimos crear un bloqueo.

Como nos estábamos quedando sin opciones, tomamos la decisión de volver a habilitar el evento beta en el juego en vivo con la intención de que los jugadores provocaran un bloqueo del servidor.

La beta “beta”

Exactamente a las 21:00, hora peninsular española (12:00, hora del Pacífico), volvimos a activar el evento beta. Nuestro chat se quedó en silencio durante unos minutos mientras esperábamos para ver qué pasaba. Antes de reactivar el evento beta, realizamos preparativos adicionales. Identificamos herramientas específicas y sistemas de supervisión para aumentar las probabilidades de detectar bloqueos y recopilar datos de depuración. Pero con lo que no contábamos era con la suerte que íbamos a tener.

Justo antes del lanzamiento de las 21:00, implementamos una nueva versión en la que estaba solucionado un fallo relacionado con las nuevas invocaciones del jugador. El primer golpe de suerte fue que la nueva versión obligó a todos nuestros servidores de juego a crear nuevos búferes de memoria compartida, con lo que se reorganizaron todas las asignaciones de memoria. A las 21:11, en nuestros monitores apareció el primer bloqueo. Muy poco después tuvimos el segundo golpe de suerte, cuando nuestros diagnósticos internos nos informaron de un bloqueo completo. Y aún tuvimos más suerte con la naturaleza de dicho bloqueo, tal como se mostraba en el archivo de volcado del sistema. Había un fragmento de código que estaba intentando eliminar una porción de memoria ya eliminada.

“¿Por qué estamos eliminando algo por duplicado?”, nos preguntábamos. “Es más, ¿por qué estamos eliminando algo de la memoria de solo lectura?”.

Lo primero que queríamos era asegurarnos de que este era el bloqueo que buscábamos y no una extraña coincidencia. Pasamos la información proveniente del análisis del archivo de volcado a nuestro equipo de control de calidad, y en 15 minutos pudimos reproducir el fallo. Mientras tanto, los miembros del equipo que supervisaban el juego en vivo habían detectado otros bloqueos; unos enviaban informes de errores y otros activaban las herramientas de monitorización de memoria que habíamos configurado previamente. Todos los informes indicaban intentos similares de leer o eliminar una sección de memoria que ya había sido eliminada. Tras un último debate para confirmar si habíamos recopilado todo lo necesario, volvimos a deshabilitar el evento beta.

Los ingenieros causan el fallo y lo arreglan

Con la amalgama, la nueva especialización de élite de la profesión de ingeniero, introdujimos una nueva y llamativa mecánica de profesión llamada transformación y una nueva ruta de código para la configuración y actualización de estas habilidades. Este nuevo comportamiento fue el que nos causó un quebradero de cabeza durante tres días.

El fallo se produjo debido a una mala interpretación de la estructura de datos que usaba la memoria local de contextos de mapa, o la memoria compartida del servidor del juego. Cuando un jugador ingeniero con la especialización de élite amalgama equipada cambiaba una habilidad de transformación mientras su recarga estaba activa, el código intentaba almacenar ese cambio de habilidad y la transferencia de la recarga relacionada con el contexto de ese jugador concreto. Ese cambio se realizaba mediante un puntero que, inadvertidamente, referenciaba a la memoria compartida. Y así, cuando pretendíamos eliminar una referencia local de la habilidad anterior, eliminábamos por accidente la habilidad de toda la memoria compartida. Cuando un jugador en ese servidor del juego volvía a intentar hacer una referencia a la habilidad de transformación ya borrada, se producía el bloqueo.

Una amalgama charr de ondulante melena plateada extiende su garra y arroja moho voluble.

Por suerte, esta estructura de datos y sus funciones de ayuda las habíamos desarrollado nosotros, por lo que técnicamente solo necesitábamos una línea para arreglar el problema.

A las 21:53, enviamos esta corrección a nuestro departamento de desarrollo y comenzamos los procesos de pruebas de errores, pruebas de regresión e introducción del cambio en las compilaciones de prueba y, por último, en las versiones finales.

Personalmente, a mí aún me fascina la rapidez con la que pudimos aplicar los cambios. En parte se debió a la magia que obró nuestro equipo de ingenieros y a “E”, que fue quien de hecho solucionó este error concreto. Pero además, nosotros tenemos algunos truquitos en nuestra cadena de compilación para agilizar las cosas. En la mayoría de las versiones de los martes, necesitamos ejecutar una compilación completa que incluya todo nuestro código y contenido. Sin embargo, si es un cambio que afecta únicamente a un fragmento de código del servidor, podemos realizar una compilación rápida. Esta versión es mucho más minimalista y selectiva, se completa en poco tiempo, y podemos enviarla rápidamente.

La beta “gamma”

Al cabo de unas horas, cuando la corrección estuvo lista en el juego en vivo, volvimos a habilitar el evento beta. Los miembros de los equipos de ingeniería y control de calidad iniciaron sesión para crear personajes de amalgama y verificar la corrección. Para nuestra tranquilidad, no se produjeron más bloqueos.

Nuestro equipo continuó con la supervisión usando las mismas herramientas que hasta entonces, y parecía que la corrección había funcionado. Nos encantó poder ofrecer por fin a los jugadores la experiencia de las nuevas especializaciones élite, con todas las habilidades y mecánicas funcionando según lo previsto.

Para concluir

Después del incidente, y tras el cierre del evento beta una semana después, nos reunimos nuevamente para recapitular, revisar y planificar. ¿Es posible detectar problemas como este de manera interna y más temprana en el proceso? ¿Existe alguna nueva herramienta o procedimiento que pueda mitigar este tipo de problemas? Si nos encontrásemos de nuevo con este problema, ¿qué medidas diferentes adoptaríamos? ¿Cómo podríamos volver más rápidamente a la normalidad?

Voy a modificar un poco la conclusión que escribí en otra publicación, allá en 2020:

Nuestros esfuerzos continuos siempre tienen como objetivo ofrecer a nuestros jugadores la mejor experiencia en nuestros servicios y la mejor manera de usarlos. Nos encanta celebrar los diseños ideados por aquellos que vinieron antes que nosotros y las herramientas y procesos que usamos para mantener nuestros altos estándares en los servidores y la calidad de las mecánicas y eventos del juego. Somos conscientes de que no hemos alcanzado la perfección, pero seguiremos apuntando a ella en cada procedimiento y despliegue futuros. A medida que esperamos las emocionantes funciones y proyectos nuevos que los equipos de mecánicas de juego y diseño os traen, nosotros seguiremos trabajando constantemente entre bambalinas para asegurarnos de que siempre podáis experimentar y disfrutar de todo lo que Guild Wars 2 ofrece.

¡Gracias de nuevo y nos vemos en Tyria!