L’emulatore MAME rinviato a dicembre

Slitta la consueta pubblicazione mensile dell’emulatore Mame che ci da appuntamento al prossimo mese di dicembre, l’ultima versione per il 2020.

La ragione di questo ritardo è semplice, e non tecnica, il team ha preso questa decisione per cercare di migliorare la stabilità complessiva del codebase, dopo alcune importanti modifiche e correggere alcuni bug riscontrati nella precedente versione 0.226.

Come per molti progetti, sono stati disposti una serie di test standard eseguiti con una certa regolarità. Quando si verifica una modifica così importante alla base del codice principale, c’è da sempre la possibilità che possano presentarsi delle instabilità. Di seguito il post pubblicato dal team MAME:

Background tecnico

La spiegazione seguente presuppone che il lettore sia un programmatore tecnicamente preparato e più esperto con linguaggi che hanno la gestione automatica della memoria, come Java o C#.

Questa sezione ha lo scopo di esaminare concetti già noti, al fine di fornire un punto di ancoraggio concettuale per contrastare la sezione successiva, che descrive in dettaglio la gestione manuale della memoria. Per chi ha una profonda conoscenza di C o C++, varrebbe la pena passare alla sezione successiva.

Sebbene ci siano molti punti per differenziare i vari linguaggi, uno dei più fondamentali è il concetto di gestione della memoria.

Ai tempi dei sistemi a 8 e a 16 bit, quando le applicazioni venivano scritte in linguaggio assembly, la RAM era estremamente limitata e si poteva essere certi che il software, e solo il software, fosse in esecuzione sull’hardware, era possibile scegliere semplicemente quale posizione nella RAM mappare direttamente e a quale variabile nel codice.

Con l’avvento dei linguaggi di livello superiore che sono fattibili per l’uso su piattaforme moderne, è stato necessario fare alcune concessioni e una di queste era la semplice domanda: Dove si trova effettivamente la mia variabile?

Un’applicazione generalmente si avvia con un footprint di memoria pari alla quantità di spazio necessaria per il codice, così come tutte le variabili che sono state in grado di essere identificate dal compilatore.

Poiché la maggior parte dell’utilizzo della memoria di un’applicazione non può essere prevista in fase di compilazione (si consideri un gioco che può generare sciami di nemici potenzialmente infiniti) la maggior parte delle lingue consente un concetto chiamato “allocazione”.

L’allocazione è, al suo livello più fondamentale, un contratto tra il programma e il sistema operativo sottostante che richiede un blocco di memoria e che quella memoria verrà eventualmente rilasciata.

Nel caso di linguaggi come Java o C#, spetta all’ambiente di runtime sottostante identificare quando verrà rilasciata la memoria. Nel caso di altri linguaggi come C o C++, questo è qualcosa che è lasciato al programmatore stesso, nel bene e nel male.

I linguaggi che forniscono una funzione per il rilascio automatico delle allocazioni di memoria sono noti come linguaggi “Garbage Collection”. In un certo senso, il programma è paragonato a una casa che semplicemente mette periodicamente fuori la spazzatura perché qualcun altro possa occuparsene.

Tuttavia, il garbage collector della lingua non dovrebbe mai essere considerato onnisciente. Alcuni atteggiamenti verso le allocazioni possono far sì che il netturbino trascorra una quantità eccessiva di tempo a ripulire dopo il programmatore, proprio come un vero netturbino se una famiglia dovesse mettere fuori centinaia di minuscoli bidoni, tutti con un solo articolo di spazzatura.

Tornando al tema dell’allocazione piuttosto che della disallocazione, un concetto importante è quello di quanta mano l’allocatore darà all’applicazione. Questo, in genere, dipende dall’applicazione stessa.

Più pertinente, il modo in cui si riferisce a C e C++ è di fondamentale importanza qui, ed è quindi dove ci troveremo nella sezione successiva.

Background (tecnico) di nuovo al fronte

C e C++, in virtù del fatto che consentono al codificatore di sovrascrivere l’allocatore o il deallocatore di sistema, presentano a detto codificatore un problema: come si gestisce la memoria non inizializzata?

Ci sono vari modi per gestirlo, ma si riduce in gran parte a tre strategie in caso di allocazione riuscita: consegnare immediatamente un puntatore al blocco allocato, lo stesso ma cancellare il blocco a zero, o anche lo stesso, ma cancellare il blocco a un valore noto diverso da zero invece.

In tutti e tre i casi, il calcolo riguarda le prestazioni. La cancellazione dell’allocazione a qualsiasi tipo di valore coerente è in genere un buon modo per evitare problemi o esporli rapidamente, ma incorre in una significativa riduzione delle prestazioni durante i periodi di utilizzo intenso dell’allocatore.

All’interno di quest’ultimo ambito, la cancellazione a un valore zero potrebbe sembrare la soluzione logica, ma così facendo si possono oscurare i puntatori non inizializzati;

Ovviamente verrà eseguito qualsiasi tipo di controllo di sicurezza del puntatore nullo nel percorso di esecuzione, quindi il programmatore potrebbe non essere nemmeno consapevole del fatto che senza un allocatore di cancellazione, il puntatore non sarebbe mai stato inizializzato.

Nel caso del primo – senza cancellare nulla – allora è del tutto sconosciuto in anticipo quali saranno i valori delle varie variabili. Potrebbero essere zero, potrebbero essere diversi da zero, saranno semplicemente qualunque cosa risiedesse in quel blocco di RAM nel momento in cui è stato consegnato dal sistema operativo sottostante.

In questo caso, queste variabili non inizializzate possono devastare la funzionalità del codice, e questo è ciò che stiamo affrontando qui nel caso di MAME.

Per decenni, MAME ha sempre assegnato la memoria e l’ha cancellata a un valore coerente. Con l’avvento del passaggio a C++ anni fa, tuttavia, un certo numero di dispositivi – implementazioni di singoli chip o periferiche – e driver – raccolte di dispositivi per emulare uno specifico sistema o piattaforma – sono stati tipicamente convertiti per essere basati su classi tanto rapidamente quanto possibile.

In tal modo, le persone che eseguivano queste conversioni di massa spesso trascuravano l’inizializzazione delle variabili dei membri della classe all’interno del costruttore della classe, perché l’allocatore di cancellazione era la grazia salvifica in questo senso.

Chiaramente trarre vantaggio dalla mancanza di chiarezza

Con il rilascio di MAME 0.226 fuori mano, è stato deciso dal nostro capo manutentore che gli svantaggi dell’utilizzo di un allocatore di compensazione superavano i vantaggi.

Sebbene manteneva una parvenza di stabilità, era in gran parte illusorio, i dispositivi e i driver sottostanti avevano ancora problemi, ma venivano mascherati.

Nel frattempo, questa decisione stava frenando le funzionalità che erano state aggiunte a MAME nel corso degli anni per promuovere l’obiettivo dichiarato di fornire documentazione.

L’enorme overhead coinvolto nella cancellazione di ogni allocazione coinvolta nella creazione di un’istanza di ogni driver, come avviene quando si richiama il comando -listxml, o il comando -validate o molti altri, era del tutto inutile in questo contesto.

Con questo in mente, è stata lanciata l’opzione e siamo passati all’uso di un semplice allocatore non azzerabile. Questo ha purtroppo avuto l’effetto collaterale di gettare in netto sollievo anni di debiti tecnici. Sebbene i nostri test automatizzati siano stati in grado di rilevare molte regressioni, non è un sistema perfetto.

A causa dell’enorme numero di sistemi che MAME emula, le esecuzioni di regressioni sono consentite per 10 secondi per sistema e vengono contrassegnate solo se si bloccano completamente o terminano con uno screenshot PNG o un output WAV che ha una differenza binaria dall’ultimo punto buono noto.

Poiché questo non supera nemmeno i test iniziali di accensione per un certo numero di giochi arcade, significa che non sappiamo necessariamente se i sistemi andranno in crash o mostreranno un comportamento non corretto oltre quel punto.

Che cosa significa tutto questo?

Come team, non possiamo in buona fede pubblicare una build questo mese senza tempo aggiuntivo per ulteriori test e ulteriori correzioni.

Il risultato che speriamo è che questo ritardo si tradurrà non solo in un’esperienza più stabile per tutti, ma anche in un’esperienza più reattiva quando si interagisce con MAME tramite la riga di comando.

Questa non è una decisione presa alla leggera, ma è anche qualcosa che non possiamo nascondere al grande pubblico. La volta precedente una data di rilascio è scivolata di un certo lasso di tempo, non solo ha danneggiato la fede del pubblico nel nostro processo di rilascio, ma ha sollevato infinite domande da parte dei fan che volevano maggiori informazioni.

Si spera che questo post fornisca maggiori informazioni non solo su ciò che stiamo facendo, ma su come e perché lo stiamo facendo.

In caso di domande relative a questa decisione, non esitare a contattare me (l’autore) personalmente tramite il mio account Twitter: @TheMogMiner.

Fonte: mamedev.org

(Visited 1 times, 1 visits today)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *