Mejora de rendimiento: Invalidación global de VALORANT
¡Hola! Soy Aaron Cheney, ingeniero de software del equipo de rendimiento de VALORANT. El rendimiento es un componente clave para mantener la integridad competitiva de VALORANT, y nuestro equipo es el responsable de supervisar, mantener y mejorar el rendimiento tanto del servidor como del cliente.
Nos complace dar una actualización sobre una función que hemos estado desarrollando durante varios meses: la invalidación global. Hablaremos de los detalles de la función más adelante, pero primero vamos a ver cómo esta función ha afectado al rendimiento del cliente desde la versión 4.03.
Alerta de spoiler: es bastante impresionante.
La invalidación global ha brindado mejoras significativas a una gran parte de nuestros jugadores. De hecho, es la mayor mejora de rendimiento para el cliente desde el lanzamiento.
Aunque las gráficas son emocionantes (y estamos muy satisfechos con los resultados), es importante entender exactamente lo que estamos viendo. Trabajamos con grupos de datos grandes y complejos; organizar, filtrar y controlar los datos nos ayuda a entender la experiencia del jugador. Esto es lo que hay que considerar para entender el panorama completo:
- La gráfica muestra la relación entre la “versión” y los “FPS promedio”; mientras más alta sea la cifra, mejor.
- Cada línea representa una configuración de hardware común (emparejamiento de CPU+GPU) de entre nuestros jugadores. Cuando analizamos los datos de rendimiento, consideramos que este emparejamiento es el factor más importante para predecir el rendimiento esperado. Las computadoras con el mismo emparejamiento de CPU+GPU se agrupan en estas gráficas.
- Las muestras de datos se toman de dos lugares: del modo normal y el modo competitivo. Dado que estos son los modos de juego más populares en VALORANT, nos esforzamos mucho por comprender y mejorar el rendimiento en estas áreas.
- Excluimos modos de juego que no tienen exactamente 10 jugadores. Esto garantiza que los valores atípicos no distorsionen los datos (los modos de juego con menos jugadores tienen un mejor rendimiento).
RESUMEN DE LA INVALIDACIÓN GLOBAL
La invalidación global genera hasta 15% de ganancia por clientes de CPU (por lo general, máquinas de especificaciones medias a altas). Obtener estos resultados fue un esfuerzo que involucró a varios equipos y llevó muchos meses. Nuestro proceso de identificación de las áreas del juego idóneas para ser optimizadas dio sus frutos, y el control de los riesgos durante el proceso contribuyó a garantizar una experiencia estable para los jugadores.
Quién se beneficia y cómo calibrar las expectativas
Con base en nuestras métricas en tiempo real, la invalidación global generó hasta 15% de mejora en las configuraciones del cliente en CPU (por lo general, máquinas de especificaciones medias a altas).
Aunque la tendencia ascendente se nota, en general, no representa la jugabilidad momento a momento. Además, no garantiza que todas las computadoras con el mismo hardware obtengan los mismos resultados.
Esto significa que el rendimiento estándar de VALORANT en computadoras que dependen de la CPU ha aumentado en general, pero el rendimiento exacto de tu computadora depende de una serie de factores únicos para ti.
ENTENDIENDO LA INVALIDACIÓN GLOBAL
Antes de que podamos explicar adecuadamente la invalidación global, primero tenemos que explicar un poco sobre los elementos de la interfaz del usuario en el Unreal Engine.
Widgets y estructuras de árbol
Los elementos de la interfaz del usuario (también conocidos como widgets) se crean a partir de componentes más pequeños utilizando una estructura de árbol. La estructura de árbol es similar al sistema de archivos de tu computadora. Un widget puede tener cualquier número de hijos (al igual que una carpeta puede tener cualquier número de archivos).
Estos componentes pueden combinarse para crear widgets complejos. Por ejemplo, nuestro contador de munición tiene muchas partes, y el árbol es algo así:
Al juntarlo todo, los componentes del contador de munición se ven de la siguiente manera:

Cada vez que uno o más widgets cambian dentro de la estructura de árbol, puede afectar a varios otros widgets. Por ejemplo, si un widget se mueve a una nueva posición en la pantalla, todos los widgets que están debajo tienen que recalcular su posición también. Estos cambios son administrados por un sistema llamado “Invalidación”, del cual hablaremos en la siguiente sección.
Invalidación
La invalidación es el mecanismo que utiliza el Unreal Engine para indicar cuando un widget específico cambia y debe ser actualizado.
Un widget necesita ser invalidado por diversas razones: la animación, el color, la opacidad, el tamaño, el orden, el texto, las imágenes y muchas otras propiedades pueden cambiar en respuesta a algo que sucedió en el juego. Cuando estos cambios afectan a un widget, este queda “invalidado”, lo que indica que debe ser actualizado.
Complicando un poco más este proceso, un widget puede tener varios tipos de invalidación. Algunos tipos son:
- Distribución: Cuando el tamaño de un widget cambia (muy costoso).
- Pintura: Cuando el aspecto del widget cambió, pero no cambió de tamaño.
- Orden de los hijos: Cuando el orden de los widgets cambia dentro del árbol (también implica la distribución, y por lo tanto es costoso).
- Visibilidad: Cuando la visibilidad de un widget cambia, ya sea que se vuelva invisible o visible (también implica la distribución, y por lo tanto es costosa).
Estos tipos de invalidación se utilizan para indicar qué tipo de operaciones hay que realizar para trazarlo correctamente.
La cosa se complica aún más cuando un widget depende de otro. Los widgets se organizan en jerarquías y su distribución depende de varios factores. Invalidar un solo widget puede requerir la invalidación de varios widgets relacionados para que se tracen correctamente. Por ejemplo, si varios widgets están ordenados en una distribución vertical (por ejemplo, el panel social con tu lista de amigos), y el orden de los widgets cambia (por ejemplo, un amigo se conecta), todos los widgets dentro de la distribución vertical deben ser actualizados.
Hay varios objetivos con un sistema como este:
- Invalidar el menor número posible de widgets. Esto reduce el número de widgets que tienen que ser actualizados a fin de trazarlos correctamente.
- Solo invalidar un widget cuando sea necesario. Invalidar incorrectamente un widget desperdicia valiosos ciclos de la CPU.
- Cuando un widget no está invalidado, guarda en caché el resultado para trazarlo rápidamente en cada cuadro. Si nada cambia, se pueden ahorrar ciclos de la CPU.
Esto es suficiente para entender cómo se actualizan los widgets y qué tipo de cosas pueden causar su invalidación. Ahora veremos cómo los desarrolladores lo ponen en práctica.
Casillas de invalidación
El Unreal Engine provee un componente, la casilla de invalidación, para agrupar a varios widgets. Todos los widgets incluidos en una misma casilla de invalidación no pueden ser predefinidos, marcados o pintados. En su lugar, el resultado se almacena en un repositorio de vértices.
Cada vez que se invalida uno de los widgets dentro de la casilla de invalidación, los datos almacenados en caché se descartan y el widget se actualiza y es pintado de nuevo. Aunque refrescar la caché puede ser costoso para un solo cuadro, el resultado optimizado es mucho mejor a largo plazo.
Las casillas de invalidación fueron un elemento clave para que la interfaz del usuario de VALORANT fuera eficaz, sobre todo durante la fase de lanzamiento. Sin embargo, no son del todo gratuitas:
- Los desarrolladores deben comprender qué widgets son buenos candidatos para agruparse con una casilla de invalidación. Cualquier widget que se actualice con frecuencia no es adecuado para esto.
- Colocar widgets dentro de una casilla de invalidación requiere de trabajo manual por parte de un desarrollador. No es posible hacerlo con todos los widgets del juego, por lo que los desarrolladores también deben saber qué widgets vale la pena poner en una casilla de invalidación.
Para más información sobre las casillas de invalidación, consulta la documentación de Epic (contenido en inglés).
¡Ahora tenemos suficiente contexto para hablar de la invalidación global!
Llega la invalidación global
A estas alturas puedes estar pensando: “¿Por qué no poner todos los elementos de la interfaz del usuario en una casilla de invalidación global?”. Bueno, eso es precisamente lo que hace la invalidación global (más o menos).
El objetivo de la invalidación global es mejorar de forma significativa el rendimiento de la interfaz del usuario en todo el juego y, al mismo tiempo, reducir el trabajo manual que deben realizar los desarrolladores para colocar los widgets en las casillas de invalidación individuales. Es lo mejor de ambos mundos.
Sin embargo, a partir de la versión UE4.25 (la versión de Unreal Engine que utiliza VALORANT), la invalidación global no es compatible con todos los tipos de widgets. Las versiones posteriores del Unreal Engine incorporaron mejoras, pero VALORANT no pudo aprovecharlas de inmediato. Además, no sabíamos muy bien qué tan rápido haría la invalidación global a VALORANT.
Aquí es donde comenzó nuestro trabajo.
¿POR QUÉ DECIDIMOS HACER ESTO?
A finales de julio de 2021, el equipo decidió probar la invalidación global durante una prueba de juego interna. Se hicieron cambios menores para corregir algunos errores con el fin de que la prueba pudiera completarse exitosamente. Sin embargo, sabíamos que habría errores durante la prueba de juego... y sin duda los encontramos.
Al final de la prueba habíamos detectado unos 20 errores, y esos eran solo los obvios. Es probable que hubiera errores más sutiles e insidiosos a la espera de ser encontrados, sin mencionar varios casos extremos que no se habían probado específicamente.
Pero... ¿la invalidación global mejoró el rendimiento? Absolutamente.
Al analizar los datos generados por esa prueba individual, se determinó que la interfaz del usuario era alrededor de un 35% más rápida. (Nota: La interfaz del usuario es solo una parte del costo de un solo cuadro).
Sin embargo, aún teníamos muchas preguntas sin responder:
- ¿Cuánto tiempo se necesita para arreglar todos los errores?
- ¿Qué equipo(s) se encargará(n) del trabajo?
- ¿Esto tiene prioridad sobre otros trabajos previstos? Para cumplir con nuestros objetivos de lanzamiento de contenidos, nuestros calendarios a menudo son establecidos con meses de antelación y los trabajos imprevistos (incluso algo tan emocionante como esto) son difíciles de incluir en el calendario.
- ¿Arreglar los errores afectaría las mejoras de rendimiento? Arreglar todos los errores requeriría muchos cambios en el código, cada uno de los cuales puede hacer que la interfaz del usuario se vuelva más costosa.
- ¿Cuándo deberíamos hacer esto? Sabiendo que la invalidación global se estaba desarrollando activamente en versiones posteriores de Unreal Engine, teníamos que tener en cuenta nuestra agenda para integrar los cambios de Epic.
Al final, decidimos que valía la pena realizar esta tarea por un par de razones.
Integraciones de Unreal Engine y consideraciones de tiempo
Aunque Unreal Engine 4.26 y 4.27 han avanzado mucho en cuanto a la invalidación global, VALORANT trabaja con un calendario de integración atrasado. La razón por la que no trabajamos con la última tecnología es para controlar el riesgo y garantizar la estabilidad a nuestros jugadores.
Como nuestro calendario establecía que permaneceríamos en Unreal Engine 4.25 durante muchos meses más, esto significaba que los jugadores no se beneficiarían de estas mejoras de rendimiento durante más de un año. Eso no nos gustó.
Para obtener más detalles sobre cómo VALORANT piensa sobre las actualizaciones de Unreal Engine, visita este hilo de Twitter del líder de tecnología de VALORANT, Marcus Reid (contenido en inglés).
Mejoras de rendimiento conocidas
La invalidación global representaba algo realmente único en términos de trabajo de rendimiento: valor calculado. Evaluamos las ganancias potenciales durante una prueba interna, y el camino para obtener ese valor estaba (casi) claro.
El trabajo de rendimiento es difícil. Es un tema de centímetros, no de kilómetros; los cambios incrementales ayudan generalmente a mejorar el rendimiento a la larga, y es raro encontrar un solo cambio capaz de proporcionar ganancias de dos dígitos. Esta era una optimización demasiado sustanciosa como para dejarla pendiente.
Incluso después de tener en cuenta la disminución de las ganancias debido a la corrección de errores, la invalidación global era la mejor oportunidad que teníamos para ofrecer ganancias significativas a los jugadores en un periodo de tiempo razonable.
¿CÓMO REALIZAMOS ESTA LABOR?
Aunque la experimentación inicial alrededor de la invalidación global comenzó a finales de julio de 2021, el trabajo serio para estabilizar la funcionalidad no comenzó hasta finales de septiembre de 2021.
Integración selectiva de los cambios de Epic
La integración completa de Unreal Engine 4.26 y 4.27 estaba descartada, pero como sabíamos que Epic había estado trabajando activamente en la invalidación global, decidimos analizar los miles de cambios e identificar cuáles podían acercarnos a una invalidación global estable y totalmente funcional.
Integrar los cambios parcialmente fue una tarea difícil. Era importante modificar el menor número posible de funciones del motor principal para mantener la estabilidad, al mismo tiempo que se introducían los cambios correctos de Epic. Todo este trabajo se hizo en una rama separada de la rama principal de VALORANT para evitar afectar a otros desarrolladores.
Después de integrar selectivamente los cambios de Epic a nuestro motor, pasamos varias semanas más arreglando todos los errores posibles mientras nos preparábamos para incorporar la invalidación global a la rama principal de VALORANT. Durante el proceso creamos un interruptor que nos permitiera activar y desactivar rápidamente la función (en caso de que ocurriera algo catastrófico).
Con muchos errores corregidos, y con muchos de los cambios hechos por Epic en las versiones 4.26 y 4.27, combinamos nuestra rama aislada con la rama principal.
Encontrar elementos comunes entre los errores
Aunque muchos de los errores con la invalidación global se manifestaban de diferentes maneras, la raíz de estos a menudo podía rastrearse a un solo problema. Corregir estos errores era muy valioso, ya que al hacerlo se podían eliminar varios problemas con un solo cambio. Por ejemplo, un cambio solucionó más de 10 errores que estaban dispersos por todo el juego. El análisis minucioso del problema raíz nos llevó a encontrar soluciones eficaces que mejoraron la seguridad y la estabilidad de la invalidación global.
Identificar y arreglar errores, probar el juego, volver a repetir
Las siguientes semanas y meses fueron un ciclo regular de activar la invalidación global antes de hacer una prueba, identificar una serie de errores, desactivar la invalidación global después de la prueba y arreglar esos errores.
Con cada iteración del bucle se registraban menos errores. Continuamos haciendo esto hasta que el flujo constante de errores se convirtió en un lento goteo, y finalmente se detuvo.
A finales de noviembre de 2021, todos los problemas principales estaban resueltos y la invalidación global era prácticamente estable.
Errores importantes
- Astra provoca una falla en el juego: En un momento dado, todos los jugadores de Astra se encontraban con una falla al cargar el juego. Este error se solucionó tras integrar los cambios de Epic.
- Falla de herencia múltiple: La herencia múltiple en C++ es un tema complicado. Sin entrar demasiado en detalles, el orden de los destructores de una clase específica no se ejecutaba en el orden correcto, lo que provocaba una falla. Con solo intercambiar el orden de herencia de 2 líneas de código se solucionó el problema. Para más información sobre las herencias múltiples, visita esta página (contenido en inglés).
- Audio del chat infinito: En los menús, la barra de chat reproduce un sonido cuando pasas el cursor por encima. Para disgusto de todos, un error hacía que ese audio se reprodujera varias veces por segundo. Corregir este error implicó entender la sincronización de cómo los widgets reciben los eventos del cursor varias veces por cuadro.
Metodologías de pruebas
Un elemento de la invalidación global que nos llevó a ser especialmente cautelosos (y, por lo tanto, minuciosos con nuestras pruebas) es que afecta a todos los aspectos del juego. Literalmente.
¿Tu lista de amigos? Absolutamente. ¿El botón que presionas para buscar una partida? Eso también. ¿El menú de ajustes? Claro que sí. ¿Mi porcentaje de tiros a la cabeza? Pues...
El punto es que los elementos de la interfaz del usuario existen en todo el juego, y a menudo transmiten información crítica a los jugadores. Romper incluso uno de esos elementos de la interfaz del usuario era inaceptable.
Con este objetivo, nuestro departamento de control de calidad creó un plan de pruebas con múltiples estrategias para garantizar que la invalidación global estaba funcionando según lo previsto.
Pruebas de corte vertical
Un “corte vertical” de VALORANT representa el camino principal que los jugadores suelen seguir, desde iniciar el cliente, buscar una partida, jugar una partida completa, hasta interactuar con la pantalla al final de la partida. Al concentrarse en los elementos críticos del juego, el departamento de control de calidad pudo probar rápidamente los elementos más utilizados del juego e identificar los problemas a tiempo.
Pruebas destructivas
Donde termina la prueba de corte vertical, continúa la prueba destructiva. Este tipo de pruebas tienen como objetivo identificar problemas fuera de lo normal, a menudo modificando factores externos (como el ping de la red, los FPS, el cambio de ventanas, etc.). Armados con un conjunto de herramientas internas, el departamento de control de calidad pasó varias semanas realizando pruebas destructivas.
Pruebas de casos extremos
Muchas partes de VALORANT solo son experimentadas por un pequeño porcentaje de los jugadores. Algunas partes del juego solo se experimentan una vez (por ejemplo, la experiencia de nuevo jugador). Que esas partes del juego sean menos frecuentadas no las hace menos importantes. Identificar y probar todos nuestros casos extremos ayudó a detectar errores escondidos.
Pruebas en el entorno de pruebas (PBE)
El entorno de pruebas fue un importante avance para la invalidación global.
- Era la primera vez que jugadores externos pudieron probar la funcionalidad. Esto significó que la invalidación global pudo ser probada en condiciones del “mundo real”.
- El PBE incluye una gran variedad de características de hardware. Abarca intencionadamente desde las especificaciones más bajas hasta las más altas, y probarlo con una gama tan amplia de dispositivos de jugadores nos dio confianza sobre el rendimiento de la invalidación global entre una base de jugadores más amplia.
Después de realizar las pruebas en el PBE durante el fin de semana del 22 al 23 de enero de 2022, teníamos la certeza de que la invalidación global no interfería con la integridad y que las mejoras de rendimiento coincidían con nuestras predicciones.
Lanzamiento de la invalidación global
Después de lanzar la invalidación global con la versión 4.03, seguimos de cerca los informes de los jugadores para detectar errores. También vigilamos atentamente los datos de rendimiento para confirmar si nuestras estimaciones coincidían con los resultados. En definitiva, la invalidación global fue un gran éxito para los jugadores, y esperamos que disfruten de la mejora de FPS.
Ahora que la invalidación global está disponible en el mundo, el equipo de rendimiento vuelve al trabajo para conseguir aún más mejoras. Hasta la próxima, ¡y felices disparos!