Nello scorso articolo abbiamo evidenziato, tramite osservazione diretta, alcune problematiche macroscopiche che rendono difficile, nello specifico, creare delle animazioni grafiche perfettamente fluide sullo smartphone Nokia 5800 XpressMusic. Riepilogo velocemente i passaggi precedenti:
- Ho creato dei testbench programmati ad hoc su Nintendo DS e su Nokia 5800 XpressMusic (Symbian 9.4)
- Dalle misurazioni effettuate risulta che, in software rendering, il Nintendo DS impiega circa 15ms per disegnare una schermata intera, mentre lo smartphone impiega solo 5ms. Non sono stati sfruttati i coprocessori grafici del DS per il test.
- Dalla misurazione del framerate risulta però che il DS ottiene 60 frames al secondo, mentre lo smartphone si assesta su una media di 20 FPS.
- Esiste quindi una latenza stimata rispettivamente in 1 millisecondo per il DS e 35 millisecondi sullo smartphone.
In questo articolo vedremo in che modo venga generata questa latenza e quali siano le possibili soluzioni per porvi rimedio.
Le prime considerazioni, come intuibile, sono relative al multitasking, cioè alla compresenza di più processi eseguiti in rapida successione dall’OS, in modo tale da dare l’impressione di essere eseguiti in parallelo.
Come funziona questo meccanismo? In breve, tutto il meccanismo si basa sul concetto di Interrupt (o interruzione).
Esiste, cioè, la possibilità di interrompere la CPU durante la sua normale esecuzione del codice, per fargli eseguire dei compiti più urgenti, e riprendere in seguito il lavoro interrotto.
Esistono tante fonti di interruzioni, ma quella che ci interessa in questo momento è data dal cosiddetto Clock Generator. Il suo funzionamento è analogo a quello del clock di sistema, che genera un segnale ad onda rettangolare usato per sincronizzare tutti i componenti del sistema.
La frequenza di questo Clock Generator può essere variata dal software, ed è in genere molto bassa rispetto al clock di sistema.
Nei dispositivi Symbian tale frequenza di interrupt si aggira intorno al millisecondo, quindi all’interno del tempo di un frame avvengono circa 15-16 interruzioni programmate.
A queste si sommano le interruzioni generate da altro hardware, tipicamente le periferiche legate alla gestione radio (GSM, UMTS, Wifi), le cui interruzioni devono essere servite con altissima priorità.
Inoltre, avviene un cambio di processo (Context Switch) alla frequenza di 64Hz (64 volte al secondo). Tale è infatti la durata del cosiddetto “tick” del kernel, cioè la durata minima assegnata all’esecuzione di ogni processo. Ciò significa che il sistema operativo interromperà il nostro processo ogni 1/64 di secondo, circa 15.6 millisecondi, mentre la durata di un frame grafico è di 16.7 millisecondi. Va da se che durante il disegno di una schermata, possiamo avere minimo 1 context switch, ma a volte sono addirittura 2 e se il processo in background ha priorità Real Time, il nostro programma dovrà aspettare ulteriormente (perdendo altri 2-3 tick) finchè questo non termina il suo task.
Questo è uno dei motivi che impediscono al nostro programma di aggiornare lo schermo esattamente 60 volte al secondo.
Il secondo, importante motivo, è dovuto al gestore del display. Sui dispositivi sprovvisti di GPU, Symbian sfrutta la normale RAM di sistema come framebuffer e si occupa di trasferire il contenuto del framebuffer al display controller tramite trasferimenti rapidi per mezzo di un canale DMA dedicato.
Il meccanismo è discretamente sofisticato, nel senso che viene inviata al display soltanto una piccola porzione rettangolare di schermo, quella contenente dati “freschi”, cioè quelle parti di schermo che sono state aggiornate. Grazie a ciò, possiamo raggiungere animazioni fluide soltanto con piccoli oggetti, in modo tale da trasferire piccole quantità di dati dalla RAM al display controller, ma quando gli aggiornamenti riguardano l’intero schermo dobbiamo sostanzialmente copiare 2 volte gli stessi dati: la prima volta dobbiamo renderizzare gli oggetti sul framebuffer tramite CPU, e la seconda volta questo framebuffer viene copiato sul controller tramite DMA.
I canali DMA hanno priorità sulla CPU quindi finchè il DMA non termina la CPU sarà ferma a girarsi i pollici. Inoltre ci sono altri canali DMA (quelli che vanno da/verso la RAM e le periferiche radio) che hanno priorità maggiore rispetto al DMA video.
Tirando le somme, ci sono 3 motivi importanti che impediscono ad un sistema di software rendering di raggiungere le prestazioni massime di 60 frames al secondo:
- I context switch non sono sincroni con l’aggiornamento dello schermo. Ciò rende impossibile temporizzare il codice, come si fa normalmente sui dispositivi dotati di temporizzazioni sincrone con lo schermo. Questa parte si potrebbe risolvere modificando il tick da 1/64 di secondo ad un sottomultiplo della frequenza di aggiornamento dello schermo, ad esempio 1/120 di secondo. Sul Nintendo DS gli interrupt non sincroni esistono (per il Wifi) ma vengono gestiti dal processore secondario. La CPU principale viene interrotta dagli interrupt di Vertical e Horizontal Blank, che non disturbano ma anzi aiutano ad aggiornare la grafica in perfetta sincronia con l’aggiornamento del display.
- I processi in Real Time hanno priorità assoluta su tutto il resto. Dal momento che in Symbian questi sono i processi legati alla gestione radio, basta disattivare le comunicazioni radio (Bluetooth, Wifi, GSM/UMTS). Ciò impedisce tuttavia la possibilità di avere giochi multiplayer che al tempo stesso siano fluidi al massimo.
- Il display controller non ha VRAM mappata in memoria, quindi richiede un trasferimento DMA alla fine del rendering di un frame. Un display dotato di VRAM mappabile in memoria (come appunto nel Nintendo DS) consentirebbe di sostituire la chiamata al DMA con un semplice bank switch, accorciando molto i tempi. Tale problema trova attualmente soluzione nei dispositivi dotati di GPU, a patto di sostituire la grafica 2D pura con grafica poligonale, in modo da evitare (o limitare al minimo) trasferimenti da RAM a GPU.
Con questo articolo spero di aver stuzzicato la vostra curiosità nei confronti dei sistemi operativi Real Time, e del funzionamento generale di un Sistema Operativo multitasking. Nei prossimi articoli entreremo dentro un tipico Sistema Operativo, e ne studieremo da vicino i meccanismi che ne consentono il multitasking.