[zxspectrum] Re: Quel brav'uomo del dottor Kendall...

  • From: Luca Bisti <lucbisti@xxxxxx>
  • To: zxspectrum@xxxxxxxxxxxxx
  • Date: Mon, 24 Jan 2005 22:53:43 +0100


Mi spieghi in quale aspetto il C sarebbe più efficiente del C++? Nel C++
paghi solo ciò che usi. Se lo usi come C avrai la stessa efficienza
(magari potresti dover disattivare la gestione delle eccezioni ma non è
neanche detto che questa porti ad una minore efficienza, anzi...).

Detto in una parola, il nostro problema era il puntatore this.
Permettimi di fare una premessa per spiegarti meglio la situazione, che risultera' estremamente pallosa e incomprensibile a chi non programma... :)


RealX e' completamente strutturato ad oggetti, con un discreto uso delle caratteristiche del C++ e quindi qualcosa devo effettivamente pagare. Ad esempio abbiamo una classe astratta DEVICE che definisce l'interfaccia di programmazione standard dei vari dispositivi emulati; la DISCiPLE e' implementata semplicemente derivando una classe da DEVICE ed implementando opportunamente i vari metodi richiesti. Non solo, uno sviluppatore esterno puo' fare altrettanto (con un semplice SDK da noi fornito, sostanzialmente un file di include) e puo' scriversi la libreria OPUS.DLL che una volta posta nella directory di RealX aggiunge automaticamente il supporto Opus Discovery a RealX.
La stessa cosa e' applicata anche ad altri livelli, ad esempio ai sistemi dei dischi e dei nastri per gestire trasparentemente i diversi formati di file esistenti; questo si faceva gia' anche con RealSpectrum in C, dove abbiamo una serie di puntatori a funzione in vari moduli per simulare ereditarieta' e polimorfismo finche' si puo'.
Bene, fin qui tutto questo ci semplifica molto la vita, permette di espandere il programma quasi all'infinito e non comporta problemi di performance perche' sono comunque componenti "periferici".


Il problema dell'efficienza del C++ ce lo siamo invece posto nel caso dei sistemi che fanno parte del loop principale dell'emulazione, primo fra tutti il core Z80.
Considera infatti che RealX deve emulare sistemi con piu' di uno Z80, ad esempio quando c'e' di mezzo il General Sound e l'FDD3000. Per vari motivi vogliamo usare una classe Z80 da istanziare quante volte vogliamo, ma ovviamente se si dichiarano i registri come variabili della classe allora ci sara' di mezzo un'indirezione di memoria in piu' dovuta al puntatore this ogni volta che accedo ad un registro dentro le routines di emulazione. Ah, l'emulazione e' scritta tutta a mano in assembler, quindi abbiamo risparmiato questi accessi piu' che potevamo!
Considera che nell'emulazione di ogni opcode si devono fare in media 4-5 accessi alle variabili che rappresentano i registri, e che vengono emulati circa 500.000 opcode al secondo in media... quei dereferenziamenti di this me li risparmio volentieri se posso, anche se il mio Athlon ha 512K di cache L2, perche' in realta' c'e' parecchia altra roba oltre ai registri e il volume dei dati da consultare e' piuttosto grosso. E poi non c'e' solo il core.
Allora abbiamo usato delle struct statiche globali, che ci eliminano il this nel codice; una sorta di contesto che pero' va gestito opportunamente per tenere coerenti le copie di queste strutture presenti nella classe. Abbiamo guadagnato il 20% sulla velocita' del core solo per aver fatto fuori il this, ma questa gestione era piuttosto incasinata e rendeva tutto molto brutto da programmare (almeno per me). Il trucco era stato esteso anche all'AY e alla ULA, gli altri due componenti che occupano piu' processore, ma ora lo abbiamo mantenuto solo per lo Z80 perche' e' l'unico guadagno apprezzabile che valga la pena di perseguire sui PC attuali.


Luca


Other related posts: