Nella mia breve (ma intensa) esperienza di sviluppo di videogames, mi è capitato di assistere ad un fenomeno interessante, che ho cercato di studiare in modo più o meno scientifico. Come ogni ricerca scientifica, il tutto parte da un’osservazione empirica, che mi ha portato ad approfondirne i meccanismi ed a rintracciarne le cause.
L’osservazione, peraltro facilmente verificabile da chiunque, è che la complessità e la fluidità grafica di un tipico gioco per Nintendo DS superano quella di gran parte dei giochi per smartphone Nokia. Nello specifico ci tengo a precisare che l’osservazione si riferisce al periodo in cui avevo iniziato a sviluppare su DS, quindi circa 3 anni fa. Ovviamente le cose sono cambiate, soprattutto dal punto di vista della “forza bruta” degli smartphone, ma il discorso ha un respiro più ampio come vi mostrerò.
Lo smartphone di riferimento per le osservazioni era un best seller della Nokia di fascia media, il vendutissimo 5800 XpressMusic. Un dispositivo senza infamia e senza lode, con una CPU della famiglia ARM11 da 434 MHz, 128 MB di memoria RAM, display da 640×360 pixel e una serie di sensori che si fanno apprezzare per lo sviluppo di giochi (accelerometro, touch screen, GPS).
Il dispositivo in questione non era dotato di accelerazione 3D in hardware, funzione che era presente sui modelli precedenti di fascia alta (N95), poi è stata eliminata (N96) e che è stata reintrodotta nuovamente dopo qualche anno (N8).
Per dovere di cronaca, le stesse osservazioni si possono fare anche con i dispositivi dotati di accelerazione 3D in hardware, ma sono meno eclatanti e quindi probabilmente non mi avrebbero spinto ad approfondirne i meccanismi.
In primis, come intuibile, la mancanza di accelerazione 3D obbliga a puntare in basso con la grafica, per ottenere un framerate dignitoso anche in software rendering.
Per appianare le divergenze ho studiato il comportamento nei giochi 2D only. Anche qui il confronto è impietoso. Grazie alla sua avanzata gestione della grafica 2D, il Nintendo DS mostra sempre scene fluide con effetti complessi (rotazione e scaling in realtime, parallax scrolling, alpha blending, ecc…), quando i giochi per il Nokia non riescono a dare schermate fluide a pieno framerate (i classici 60 FPS degli schermi LCD) nemmeno con una semplice pallina che rimbalza su uno sfondo perfettamente statico.
Datasheet e calcolatrice alla mano, il tempo necessario per effettuare il disegno dello schermo, sul dispositivo Nokia, è di 5 millisecondi, e tra un frame e l’altro ci sono “ben” 16,7 millisecondi di tempo per far tutto.
Il framerate più “roseo” che riesco ad ottenere si assesta sui 20 FPS, ciò significa che il tempo necessario al dispositivo per generare una schermata è compreso tra 33.3 e 50 ms, diciamo 40 ms in media.
Se vi state chiedendo come ho fatto i calcoli, considerate che in condizioni stazionarie (tempo di rendering costante per ogni frame), aggiornando lo schermo soltanto durante il periodo di Vertical Blank, posso ottenere soltanto un sottomultiplo intero di 60 FPS, quindi 30, 20, 15, 12 e così via. Inoltre considero una stima per eccesso di 10 cicli di clock per disegnare un pixel senza alpha blending (stima ricavata empiricamente tramite codice scritto ad hoc).
Quindi se ho 640×360 pixel, e impiego 10 cicli di clock per pixel, mi serviranno circa 2.3 milioni di cicli di clock per aggiornare lo schermo. Ad una frequenza di clock di 434MHz, bastano 5.3 millisecondi per completare l’operazione, a cui si aggiungono 35 ms circa di overhead per arrivare ai 40ms calcolati precedentemente.
Rifacendo i calcoli sul Nintendo DS, usando un algoritmo di software rendering che impiega circa 20 cicli di clock per pixel (il DS fa il doppio dei cicli a causa del bus a 16 bit della Ram), otteniamo: 256×192 pixel x 20 cicli = 983040 cioè quasi un milione di cicli di clock necessari, che con una CPU a 67MHz significano circa 15 ms. Sul DS ottengo, nonostante tutto, 60 FPS pieni, quindi a questi 15 ms si aggiunge pochissimo overhead, rientrando perfettamente nel limite dei 16.7 ms necessari per l’aggiornamento dello schermo. Nel caso peggiore abbiamo sul DS circa 1 ms di overhead, contro i 35 ms misurati sullo smartphone, usando in entrambi i casi un algoritmo di software rendering.
A questo punto la questione si sposta sul sistema operativo sottostante, Symbian OS.
Symbian OS è un sistema operativo multitasking, con caratteristiche Real Time. La parola Real Time non deve trarre in inganno: Real Time non è un sinonimo di “veloce” e nemmeno di “multimediale”. Un sistema operativo si definisce Real Time quando offre la possibilità di schedulare dei task con precise indicazioni di deadline. In altre parole, un sistema operativo si dice Real Time quando mi consente di chiedergli “mi serve che tu esegua questo task entro i prossimi 300 millisecondi” e mantiene le promesse in modo deterministico, cioè accetta la richiesta soltanto se sa di poter mantenere la promessa, altrimenti la rifiuta.
Il sistema, per garantire le deadline, deve effettuare dei calcoli ed accettare il task soltanto se è sicuro al 100% di rispettare tale deadline.
Il “come” è una materia estremamente complessa e mi scuso per la necessaria approssimazione che sto per fare. Nel caso specifico di Symbian OS, i task con deadline garantite sono quelli che gestiscono le comunicazioni radio. Cascasse il mondo, il task che si occupa di gestire la rete deve assolutamente essere eseguito entro i tempi prestabiliti. Ciò significa che esistono processi di serie A e processi di serie B (per così dire), e le applicazioni utente ricadono nella seconda categoria.
L’overhead misurato ricade in larga percentuale sui meccanismi necessari alla gestione di questi preziosissimi task, e in percentuale minore ad altri processi di serie B che concorrono all’assegnazione delle risorse con il nostro videogame, come ad esempio i processi che smistano gli eventi di sistema, il filesystem, la telefonia, il livello di carica della batteria, l’aggiornamento dei sensori, ecc…
Di contro, il Nintendo DS non ha alcun sistema operativo sottostante, quindi spetta al programmatore rispettare le proprie deadline (nel nostro caso, comporre la prossima schermata entro e non oltre i prossimi 16 millisecondi).
Nel prossimo articolo approfondiremo i meccanismi interni di un RTOS (Real Time Operating System) e cercheremo di capire se e come questi meccanismi possono essere d’aiuto nello sviluppo di videogiochi.
Molto interessante :)
Da profanissimo della materia sono estremamente interessato alla tua indagine… argomento molto intrigante!
ottimo articolo!
anzie eccellente!
Possibile che per trasferire un buffer in memoria nel framebuffer si perda così tanto tempo? :-O
@Cesare: i tempi misurati sono quelli, e ho scoperto in seguito anche il perchè… lo mostrerò nel prossimo articolo O:-)
ora sto per dire una mostruosità, ma parlo da uomo della strada: ma in pratica un commodore 64 (1982, 8 bit ed un megahertz, piu’ coprocessore custom vic2) è piu’ veloce di un arm11 con 434 volte la velocità in megahertz? (nei videogiochi, ovvio)
Assolutamente no :-)
la quantità di dati da spostare per disegnare lo schermo, nel C64, sono inferiori di 3 ordini di grandezza (1.000 bytes contro 691.200 bytes). Inoltre quella cpu ARM11 è 4 ordini di grandezza più veloce del 6510, quindi non c’è paragone :-)
mmmh forse anche 5 ordini di grandezza superiore :-)
complimenti per l’articolo, aspetto con impazienza la seconda parte :)
ps: ma come si fa per avere una foto al posto della sagoma?
lol come non detto, ma siete collegati a gravatar?
grazie! Tutti i siti basati su WordPress possono appoggiarsi a Gravatar senza sforzo, dal momento che è supportato ufficialmente da tale CMS :-)
ahhhhhh!!! ok, grazie mille!!
Una domanda: facendo andare il Nokia in modalità “aereo”, disabilitando la baseband e tutto ciò che ha a che fare con le varie parti radio, non si “sgancia” il ferreo e pesante sincronismo tra parte squisitamente radio e squisitamente software consentendo alle applicazioni di avere più tempo per l’esecuzione?
da profano direi che hai fatto il confronto con un cellulare con hardware datato (adesso le cpu vanno a 1ghz e sono in procinto di uscire quelle da 1,2 dual-core) e sistema operativo datato… non so se con android le cose vadano meglio rispeto a symbian, che non sara “real-time” ma essendo una versione ottimizzata di linux, ci si può far girare ottime librerie ultra collaudate e perfezionate negli anni…
@javelin: la tua intuizione è corretta. Alcuni task a priorità real time vengono sospesi e le latenze si abbassano di molto. Tuttavia ci sono alcune cose, che tratterò nel prossimo articolo, che sono intrinseche del sistema operativo e determinano una penalità praticamente per tutte le applicazioni facenti pesante uso del display :-)
@marco: da questo punto di vista, Symbian OS è decisamente più avanzato di Android, quindi il confronto sarebbe stato ancora più massacrante :-)
Prova ad usare un gioco qualsiasi su di un terminale Android privo di accelerazione 3D hardware e vedrai che le prestazioni grafiche sono bassissime nonostante la CPU sia molto potente.
In ogni caso vorrei farti notare che il confronto è fatto con l’ancora più vetusto e obsoleto Nintendo DS, che ha una CPU più lenta di 1 ordine di grandezza, 25 volte meno memoria RAM e un bus di sistema a 16 bit :-)
E’ chiaro che il problema sta nel sistema operativo, e non nell’hardware, e mostrerò in seguito i motivi :-)
…facendo 2 conti il mio htc hd2 andando a 1ghz è 2,3 volte più veloce del nokia, questo vuol dire che avrei ottenuto non 20 fps ma 46 e non saprei quantificare che miglioramento (o peggioramento) ci può essere a lavorare sotto linux avendo a che fare probabilmente con le SDL 1.2.
Certo anche così fa una certa impressione pensare che un Nintendo DS a 67mhz faccia meglio di una CPU a 1ghz, ma stiamo parlando di software render sul cellulare, dobbiamo anche aggiungerci che i nuovi smarthphone hanno processori dedicati all’accelerazione grafica…
@marco: il tuo ragionamento sarebbe valido se non ci fosse il sistema operativo. In caso di sistemi con preemptive multitasking, il calcolo algebrico delle frequenze dei componenti perde totalmente di significato. Comunque se rileggi l’articolo, ho usato il software rendering anche sul DS proprio per “normalizzare” i risultati ed escludere le accelerazioni grafiche hardware di qualunque genere (2D e 3D) ;-)
Il fatto della penalità per le applicazioni facenti pesante uso del display mi ha ricordato lo ZX80 Sinclair, dove la CPU lasciava perdere tutto e si dedicava alla gestione del video, alla bisogna, con conseguente mancanza di quadro quando doveva far girare i programmi! :)
@javelin: per fortuna non siamo a questi livelli drammatici :-D
In quel caso pur di risparmiare qualche sterlina in più, mister Sinclair aveva affidato al software la gestione di una cosa prettamente di competenza hardware (la generazione del quadro).
Qui il problema sta nella “troppa” sofisticazione della piattaforma :-)
Volendo fare un paragone, un semplice blitting su schermo, in un moderno smartphone, passa attraverso tante di quelle peripezie che sarebbe come salire al secondo piano di una palazzina usando una funivia e un carroarmato. :-D
“Ciò significa che esistono processi di serie A e processi di serie B (per così dire), e le applicazioni utente ricadono nella seconda categoria.”
E’ un os per cellulari ed il suo scopo primario è comunicare. Scommetto che se prendessimo il famoso QNX “quello che gestisce le centrali nucleari” e cominciassimo a fargli girare tetris, pur di evitare che qualche modulo di sicurezza scatti in ritardo, ci farebbe ballare il casatschok con il ritmo di un lento da balera.
@[D]
eheh bella analogia :D
hai scoperto l’acqua calda :D si sa che se c’è sotto un sistema operativo le cose rallentano, inoltre devi considerare che sul ds il programmatore comanda direttamente l’hardware (in linguaggio assembly o simile, suppongo, quindi a bassissimo livello), mentre sullo smartphone devi passare per librerie grafiche, chiamate di sistema, eccetera. è lo stesso motivo per cui un pc con hardware del 2005 non riesce ad eseguire dignitosamente i giochi recenti, mentre console con lo stesso hardware riescono (nella maggioranza dei casi) ad offrire grafica perlomeno guardabile e performance dignitose anche su hardware così limitato.
o almeno, così la penso io :D
ad ogni modo complimenti per l’articolo, interessante
grazie per i complimenti :-)
purtroppo sono un po’ limitato e ci arrivo con i miei tempi a scoprire che l’acqua calda è calda… ma l’importante alla fine è arrivarci ;-)
@dosse: il s.o. di per sé non è la causa di tutti i mali, visto che ne esistono di “super lightweight”.
Non credo che Antonio nel suo articolo volesse generalizzare. Per lo meno, da quel che ho letto, il suo mi sembra più che altro un “caso d’uso”, un’esperienza vissuta, sebbene molto comune in ambito smartphone.
@cesare di mauro: mi sono espresso male evidentemente. quello che intendevo dire è che nell’esecuzione del codice del videogioco su pc, piuttosto che su smartphone, ci sono più livelli intermedi, librerie grafiche, driver, funzioni del sistema operativo, eccetera, mentre sulle console questo non accade, o è estremamente semplificato e più veloce
@dosse: sulle console ci sono esattamente le stesse librerie grafiche, driver e ormai hanno messo dentro pure dei completi sistemi operativi.
Però sai… se il tick del kernel cade 64 volte in un secondo, invece di 60, e se il display ha bisogno di un DMA transfer per ogni aggiornamento dello schermo… ti rendi conto che… è meglio aspettare il prossimo articolo :-D