Miglioramento prestazioni: invalidazione globale di VALORANT

Questa è la storia di come il team delle prestazioni di VALORANT ha reso il client di gioco più performante.

Ciao! Sono Aaron Cheney, un ingegnere informatico del team delle prestazioni di VALORANT. Le prestazioni sono un elemento fondamentale per mantenere l'integrità competitiva di VALORANT, e il nostro team ha il compito di monitorare, preservare e migliorare le prestazioni di client e server.

Siamo lieti di parlarvi di una funzionalità che stiamo sviluppando da parecchi mesi: l'Invalidazione globale. Scenderemo a breve nei dettagli, ma prima vediamo l'impatto che questa funzionalità ha avuto sulle prestazioni del client dalla patch 4.03.

Senza girarci troppo attorno: è davvero incredibile.

AskVal_March22_Global_Invalidation_Graph_3.jpg

L'invalidazione globale ha offerto un notevole miglioramento delle prestazioni a moltissimi giocatori. Anzi, è il più grande miglioramento delle prestazioni del client dall'uscita del gioco.

I dati di questi grafici sono esaltanti (siamo felicissimi dei risultati), ma è importante che capiate bene cosa state leggendo. Lavoriamo con set di dati grandi e complessi; organizzare, filtrare e controllare i dati ci aiuta a capire meglio l'esperienza dei giocatori. Ecco cosa dovete sapere per comprendere il quadro generale:

  • Il grafico mostra la "patch" in rapporto al "framerate medio"; i numeri più alti sono migliori
  • Ogni linea rappresenta una configurazione hardware comune tra i nostri giocatori (abbinamento CPU+GPU). Quando analizziamo i dati delle prestazioni, consideriamo questo abbinamento come l'indicatore più importante per le prestazioni previste. Questi grafici aggregano i computer con lo stesso abbinamento CPU+GPU
  • I campioni di dati sono presi da due code: non competitiva e competitiva. Dal momento che si tratta delle modalità di gioco più popolari di VALORANT, ci impegniamo molto per comprendere e migliorare le loro prestazioni
  • Abbiamo escluso le partite che non hanno esattamente 10 giocatori. Questo per assicurare che tali anomalie non alterassero i dati (le partite con meno giocatori hanno prestazioni migliori)

RIEPILOGO SULL'INVALIDAZIONE GLOBALE

global-invalidation-summary-flow.jpg

L'invalidazione globale consente un miglioramento fino al 15% nei client in cui il collo di bottiglia è costituito dal processore (in genere computer di fascia media e alta). Questi benefici sono il risultato di uno sforzo che ha coinvolto vari team e che ha richiesto molti mesi di lavoro. Siamo riusciti a individuare le parti del motore di gioco che avevano margini di miglioramento e la gestione dei rischi ci ha permesso di assicurare ai giocatori un'esperienza stabile.

Chi beneficia di questi miglioramenti?

Considerando i nostri dati telemetrici aggiornati costantemente, l'invalidazione globale ha migliorato fino al 15% le prestazioni di configurazioni del client in cui il collo di bottiglia è costituito dal processore (in genere computer di fascia media e alta).

Mentre nel complesso è evidente una tendenza verso l'alto, questa non rappresenta necessariamente gameplay specifici. Inoltre, questo non garantisce che tutti i computer con lo stesso hardware abbiano risultati identici.

Questo significa che le prestazioni base di VALORANT sui computer in cui il collo di bottiglia è costituito dal processore sono generalmente migliorate, ma le prestazioni esatte del vostro computer dipendono da una serie di altri fattori esclusivi.

COMPRENDERE L'INVALIDAZIONE GLOBALE

Prima di fornirvi una buona panoramica sull'invalidazione globale, dobbiamo illustrarvi gli elementi dell'interfaccia in Unreal Engine.

Widget e strutture ad albero

Gli elementi dell'interfaccia (chiamati anche widget) vengono creati a partire da elementi costitutivi più piccoli, utilizzando una struttura ad albero. La struttura ad albero è simile al file system del vostro computer. Un widget può avere un numero qualsiasi di "figli" (proprio come una cartella può contenere un numero qualsiasi di file).

Questi elementi costitutivi possono essere combinati per creare widget complessi. Ad esempio, il nostro contatore delle munizioni è formato da diverse parti e l'albero è fatto più o meno così:

Screenshot_2022-03-07_at_16-30-57_PRF_-_Global_Invalidation_article.png


Tutti insieme, gli elementi costitutivi del contatore delle munizioni appaiono così:


AskVal_March22_Valorant_UI_Elements.jpg

(I bordi rossi di delimitazione sono stati esagerati nelle dimensioni per una maggiore chiarezza. In realtà, molti si sovrappongono.)

Ogni volta che uno o più widget cambiano all'interno della struttura dell'albero, possono esserci effetti su altri widget. Se, per esempio, un widget si sposta in una nuova posizione dello schermo, deve essere ricalcolata anche la posizione di tutti i suoi figli. Queste modifiche vengono gestite da un sistema chiamato "Invalidazione", di cui parleremo nella sezione successiva.

Invalidazione

L'invalidazione è il meccanismo che l'Unreal Engine utilizza per indicare quando un particolare widget è cambiato e necessita di un aggiornamento.

Ci sono vari motivi per cui un widget deve essere invalidato: animazione, colore, opacità, dimensioni, disposizione, testo, immagini e molte altre caratteristiche possono cambiare a seguito di qualcosa che succede nel gioco. Quando queste modifiche avvengono in un widget, questo viene "invalidato" per indicare la necessità di un aggiornamento.

Per complicare ancora di più le cose, un widget può avere più tipi di invalidazione. Eccone alcuni:

  • Struttura - Quando cambiano le dimensioni di un widget (molto costoso a livello di prestazioni)
  • Colore - Quando il widget ha cambiato aspetto, ma non dimensioni
  • Ordine dei figli - Quando è cambiato l'ordine dei widget all'interno dell'albero (coinvolge anche la struttura e quindi è molto costoso a livello di prestazioni)
  • Visibilità - Quando un widget passa da visibile a invisibile, o viceversa (coinvolge anche la struttura e quindi è molto costoso a livello di prestazioni)

Questi tipi di invalidazione servono a indicare quali operazioni vanno eseguite per renderizzarlo correttamente.

Tutto si complica ancora di più quando un widget dipende da un altro widget. I widget sono organizzati in gerarchie e la loro struttura dipende da una serie di fattori. Invalidare un singolo widget può richiedere l'invalidazione di altri widget collegati, al fine di ottenere un rendering corretto. Per esempio, se più widget sono organizzati in una struttura verticale (per esempio il pannello social nell'elenco amici) e l'ordine dei widget cambia (per esempio quando un amico si collega), tutti i widget della struttura verticale vanno aggiornati.

Un sistema del genere ha diversi obiettivi:

  • Invalidare il numero minore possibile di widget. Questo riduce il numero di widget che devono essere aggiornati per renderizzare correttamente l'interfaccia
  • Invalidare un widget solo quando è necessario. Invalidare inutilmente un widget spreca risorse preziose del processore
  • Quando un widget non deve essere invalidato, salvare in cache il risultato per renderizzarlo rapidamente in ogni frame. Se non cambia nulla, è possibile risparmiare risorse del processore

Queste informazioni tecniche sono sufficienti per capire come si aggiornano i widget e quali sono le ragioni che possono portare all'invalidazione. Ora vediamo come gli sviluppatori mettono in pratica tutto questo.

Invalidation Box

L'Unreal Engine ha un elemento, chiamato Invalidation Box, che serve a raggruppare più widget. Tutti i widget di un singolo Invalidation Box non sono soggetti a pre-pass, ticking o ricolorazione. Il risultato viene invece salvato in un buffer di vertici.

Quando uno dei widget dell'Invalidation Box viene invalidato, i dati nel buffer vengono eliminati e il widget viene aggiornato e colorato di nuovo. Anche se aggiornare il buffer può essere esoso per un singolo frame, il risultato è di gran lunga migliore nel lungo periodo.

Gli Invalidation Box sono fondamentali per l'ottimizzazione dell'interfaccia di VALORANT e lo sono stati soprattutto in vista del lancio. Il procedimento, tuttavia, non è semplice:

  • Gli sviluppatori devono capire quali widget possono essere riuniti in un Invalidation Box. Un widget che deve aggiornarsi spesso non è adatto
  • Inserire widget in un Invalidation Box richiede un intervento manuale da parte di uno sviluppatore. Non è possibile farlo per ogni widget del gioco, perciò gli sviluppatori devono anche capire quali widget vale la pena inserire in un Invalidation Box

Per ulteriori informazioni sugli Invalidation Box, consultate la documentazione di Epic Games.

Ora abbiamo abbastanza contesto per parlare dell'invalidazione globale!

Cos'è l'invalidazione globale

A questo punto potreste chiedervi: "Perché non mettere tutti gli elementi dell'interfaccia in un Invalidation Box globale?" Beh, è esattamente quello che fa l'invalidazione globale (più o meno).

L'invalidazione globale punta a migliorare in maniera significativa le prestazioni dell'interfaccia nel gioco, riducendo al contempo gli interventi manuali degli sviluppatori per posizionare i widget nei singoli Invalidation Box. È una situazione ideale.

Tuttavia, l'invalidazione globale dell'Unreal Engine 4.25 (la versione utilizzata da VALORANT) non è supportata da tutti i tipi di widget. Le versioni successive dell'Unreal Engine hanno migliorato la situazione, ma VALORANT non ha potuto approfittarne subito. Inoltre, non avevamo ancora stimato quanto più prestante sarebbe stato VALORANT grazie all'invalidazione globale.

E qui è iniziato il nostro lavoro.

PERCHÉ ABBIAMO DECISO DI FARE TUTTO QUESTO?

Alla fine del mese di luglio 2021, il team ha deciso di sottoporre l'invalidazione globale a una serie di test di gioco interni. Abbiamo implementato alcune piccole correzioni di bug in modo da completare con successo i test di gioco. Ciò non significa che non ci aspettassimo l'emergere di altri bug nei test… e così è stato.

Alla fine dei test avevamo individuato circa 20 bug... e si trattava solo di quelli evidenti. Altri, più subdoli e insidiosi, erano in attesa di essere scoperti, per non parlare di diversi casi limite che non erano stati testati in maniera specifica.

Ma, in fin dei conti, l'invalidazione globale ha migliorato le prestazioni? Assolutamente sì.

Analizzando i dati di quel singolo test di gioco, l'interfaccia è risultata più veloce di circa il 35%. (Nota: l'interfaccia è solo parte del costo di un singolo frame).

Ad ogni modo, rimanevano ancora molte domande aperte:

  • Quanto tempo sarebbe servito per correggere tutti i bug?
  • Quali team avrebbero dovuto occuparsene?
  • Questo lavoro doveva avere la priorità su altre cose già in programma? In genere programmiamo tutto con mesi di anticipo per pubblicare contenuti a cadenza regolare e un nuovo lavoro, per quanto esaltante, è sempre difficile da mettere in scaletta
  • Correggere i bug avrebbe annullato i miglioramenti alle prestazioni? Correggere tutti i bug avrebbe richiesto molte modifiche al codice, ciascuna delle quali avrebbe potuto aumentare il costo di rendering dell'interfaccia
  • Quando avremmo dovuto svolgere questo lavoro? Sapere che l'invalidazione globale era in corso di sviluppo nelle versioni più recenti dell'Unreal Engine significava dover riconsiderare le nostre tempistiche per integrare le modifiche di Epic Games

Alla fine abbiamo deciso che ne valeva la pena per un paio di motivi.

Integrazioni dell'Unreal Engine e tempistiche

Anche se le versioni 4.26 e 4.27 dell'Unreal Engine hanno migliorato notevolmente l'invalidazione globale, VALORANT opera con un programma di integrazione in differita. Il motivo per il quale non lavoriamo con la tecnologia più recente e all'avanguardia è che vogliamo ridurre i rischi e garantire maggiore stabilità ai nostri giocatori.

Dal momento che, da programma, saremmo rimasti all'Unreal Engine 4.25 per molti altri mesi, ciò avrebbe comportato che i giocatori non avrebbero beneficiato delle prestazioni migliorate per più di un anno. E questo non ci piaceva.

Per maggiori dettagli sulla filosofia di VALORANT riguardo agli aggiornamenti dell'Unreal Engine, potete consultare questa discussione su Twitter di Marcus Reid, capo tecnico di VALORANT.

Miglioramenti noti alle prestazioni

L'invalidazione globale rappresentava qualcosa di davvero unico in termini di prestazioni: un valore misurabile. Abbiamo misurato i guadagni potenziali durante un test di gioco interno e il percorso per ottenere quel valore era (in gran parte) chiaro.

Lavorare sulle prestazioni è difficile. Bisogna muoversi a piccoli passi; le modifiche incrementali aiutano a migliorare le prestazioni in generale nel tempo ed è difficile trovare una singola modifica in grado di assicurare miglioramenti a due cifre. Questa era un'ottimizzazione troppo invitante per lasciarla nel cassetto.

Anche tenendo conto dell'impatto minore sulle prestazioni dovuto alla correzione dei bug, l'invalidazione globale restava la nostra migliore possibilità per offrire ai giocatori un framerate più alto in tempi ragionevoli.

COME CI SIAMO RIUSCITI?

Anche se i primi esperimenti con l'invalidazione globale sono iniziati a fine luglio 2021, abbiamo cominciato a impegnarci concretamente per stabilizzare la funzionalità non prima di settembre 2021.

L'integrazione selettiva delle modifiche di Epic Games

L'integrazione completa dell'Unreal Engine 4.26 e 4.27 era fuori discussione. Tuttavia, poiché sapevamo che Epic Games aveva lavorato attivamente sull'invalidazione globale, abbiamo deciso di analizzare migliaia di modifiche e identificare quelle maggiormente in grado di avvicinarci a un'invalidazione globale stabile e del tutto funzionante.

Integrare le modifiche in modo parziale è stato molto impegnativo. Era importante modificare il minor numero possibile di funzionalità centrali del motore grafico, per mantenerne la stabilità mentre sceglievamo le modifiche apportate da Epic Games che ci interessavano. Tutto questo lavoro è stato svolto su una versione separata di VALORANT rispetto a quella principale, per evitare ripercussioni sugli altri sviluppatori.

Dopo aver integrato selettivamente le modifiche di Epic Games nel nostro motore grafico, abbiamo trascorso diverse settimane a correggere il maggior numero possibile di bug, mentre ci preparavamo a implementare l'invalidazione globale nella versione principale di VALORANT. Durante questo periodo, abbiamo aggiunto la possibilità di attivare e disattivare velocemente la funzionalità (a scanso di eventuali catastrofi).

Una volta corretti molti bug e incluse molte delle modifiche di Epic Games dalle versioni 4.26 e 4.27, siamo usciti dal nostro isolamento per riunirci alla versione principale di VALORANT.

Trovare elementi in comune tra i bug

Anche se molti dei bug dell'invalidazione globale si manifestavano in modi diversi, spesso la causa alla radice era sempre la stessa. Questi erano i bug più importanti da correggere, perché in questo modo sarebbe stato possibile eliminare più problemi con una sola modifica. Un intervento, per esempio, ha corretto più di 10 bug presenti nel gioco. L'analisi accurata del problema alla radice ha portato a soluzioni valide che hanno migliorato affidabilità e stabilità dell'invalidazione globale.

Identificare i bug, correggerli, fare test di gioco e ripetere a oltranza

Nelle settimane e nei mesi successivi ripetevamo regolarmente questo ciclo: attivare l'invalidazione globale prima di un test di gioco, identificare una serie di bug, disattivare l'invalidazione globale dopo il test e correggere i bug.

developer-bug-fix-flow.jpg


A ogni ripetizione del ciclo, i bug segnalati diminuivano. Abbiamo proseguito con questo metodo e pian piano i bug sono diventati sempre meno, fino a sparire del tutto.

Per la fine di novembre 2021, tutti i problemi principali erano stati risolti e l'invalidazione globale era praticamente stabile.

Bug in evidenza
  • Astra manda in crash il gioco - A un certo punto, tutti i giocatori di Astra venivano accolti da un bel crash quando provavano ad entrare in partita. Questo bug è stato risolto dopo l'integrazione delle modifiche di Epic Games
  • Crash legato all'ereditarietà multipla - L'ereditarietà multipla in C++ è un argomento complesso. Senza scendere troppo nei dettagli, l'ordine di esecuzione dei distruttori in una determinata classe non era corretto e mandava il gioco in crash. È bastato invertire due righe di codice per cambiare l'ordine di ereditarietà e risolvere il problema. Per maggiori informazioni sull'ereditarietà multipla, consultate questa pagina
  • Chat audio infinita - Nei menu, la barra della chat riproduce un suono quando ci si passa sopra con il mouse. A causa di un bug molto seccante, quell'audio veniva riprodotto più volte al secondo. Per correggerlo, abbiamo dovuto capire la tempistica con cui i widget ricevono gli input del mouse più volte per frame

    Testare le metodologie

    Un elemento dell'invalidazione globale che ci ha messo particolarmente in guardia (e al quale siamo stati molto attenti durante i test) è il fatto che interessa qualunque aspetto del gioco. Letteralmente.

    Il vostro elenco di amici? Lo riguarda. Il pulsante che premete per mettervi in coda? Anche quello. Il menu delle impostazioni? Potete giurarci. La percentuale di colpi alla testa che mettete a segno? Vabbè, ora non allarghiamoci...

    Il punto è che gli elementi dell'interfaccia esistono in tutto il gioco e spesso comunicano informazioni fondamentali ai giocatori. Danneggiare anche uno solo di questi elementi dell'interfaccia sarebbe stato inaccettabile.

    Per questo, il nostro team del controllo qualità ha creato un piano di collaudo con strategie multiple per assicurarci che l'invalidazione globale funzionasse come previsto.

    Test della sezione verticale

    Una "sezione verticale" di VALORANT rappresenta il percorso principale che i giocatori intraprendono di solito: avviare il client, entrare in coda per una partita, giocare una partita completa, interagire con la schermata di fine partita. Concentrandosi sugli elementi critici del gioco, il team del controllo qualità ha potuto testare rapidamente gli elementi più utilizzati e identificare prima i problemi.

    Test distruttivi

    Se i test della sezione verticale snelliscono, quelli distruttivi accumulano. Questo tipo di test serve a identificare problemi contingenti, spesso modificando fattori esterni (per esempio ping della rete, framerate, comando Alt+Tab, ecc.). Armato di una serie di strumenti interni, il team del controllo qualità ha dedicato diverse settimane ai test distruttivi.

    Test dei casi limite

    Molte parti di VALORANT vengono sperimentate solo da una piccola percentuale di giocatori. Alcune, addirittura una volta sola (ad esempio l'Esperienza nuovo giocatore). Ma solo perché queste parti sono meno comuni non significa che siano meno importanti. Identificare e testare tutti i nostri casi limite ci ha aiutato a scovare errori nascosti.

    Test sul PBE (Public Beta Environment)

    Approdare al PBE è stato un grande traguardo per l'invalidazione globale.

    • Era la prima volta che i giocatori potevano testarne la funzionalità. Voleva dire testare l'invalidazione globale in condizioni "reali"
    • Sul PBE gira una grande varietà di configurazioni hardware. Il PBE abbraccia intenzionalmente PC di ogni fascia, da bassa ad alta. I test con un numero così elevato di hardware ci hanno dato maggiore sicurezza sulle prestazioni dell'invalidazione globale per tutti i giocatori

    Dopo i test sul PBE condotti nel weekend del 22-23 gennaio 2022, abbiamo avuto la conferma che l'invalidazione globale non interferiva con l'integrità competitiva e che i miglioramenti delle prestazioni erano in linea con le nostre previsioni.

    Uscita dell'invalidazione globale

    Dopo l'uscita dell'invalidazione globale con la patch 4.03, abbiamo monitorato con attenzione le segnalazioni di bug effettuate dai giocatori. Abbiamo anche tenuto d'occhio i dati delle prestazioni, per vedere se le nostre stime corrispondevano ai risultati. Alla fine, l'invalidazione globale è stata un grande successo per i giocatori e speriamo siate soddisfatti dei miglioramenti al framerate.

    Ora che l'invalidazione globale è a disposizione di tutti, il team delle prestazioni si è rimesso al lavoro per portarvi ulteriori miglioramenti. Alla prossima e buon VALORANT!