Lento? Ma quando?

A suo tempo quando la mia azienda programmava in C++, io e il mio socio eravamo impegnati in un progetto che aveva un tempo di sviluppo/consegna previsto di un anno. Effettuammo quindi dei test per capire se Java era accettabile in termini di prestazioni in un ambiente enterprise (non era per fare applet). Il processore di punta Intel era un PentiumPro a 200 MHz. Fatti i test arrivammo a questa conclusione: Java era più lento ma grazie alla legge di Moore avremmo ottenuto delle macchine con prestazioni più che adeguate non rimpiangendo il codice C++. Mal che vada si poteva deviare su dei RS/6000. Non solo dopo un anno avemmo quelle macchine ma avemmo anche un nuovo garbage collector, un JIT e una virtual machine IBM assai più performante di quella Sun. In conclusione noi accelerammo i tempi di sviluppo ottenendo codice più corretto e più performante. E un ambiente più semplice da imparare per i neoassunti. E questi vantaggi ebbero una notevole ricaduta anche sul cliente finale. Dal quel momento, nonostante ne fossimo esperti, abbandonammo completamente il C++ come strumento principale di sviluppo per un una gran parte delle varie tipologie di applicazioni.

Oggi ero da un cliente e ho avuto occasione di chiaccherare con dei tecnici. Il discorso è caduto sulle prestazioni dei programmi .NET e Java. In pratica queste persone sostenevano che i programmi .NET e Java erano lenti.

Premettendo che i programmi scritti bene in C/C++ sono sicuramente più veloci e aggiungendo il fatto che i programmi scritti bene in assembler sono probabilmente ancora più veloci, qui mi sembra che sfuggano alcuni punti fondamentali che è bene ribadire.

Scrivere buon codice è difficile e costoso. La gestione corretta della memoria è probabilmente una delle attività più complesse e soggette ad errori. Se si riesce a fare in modo che sia il runtime a gestire la memoria si riesce ad eliminare di colpo una grande fonte di potenziali problemi. Gli ambienti di esecuzione basati su VM (Virtual Machine) come quelli di Java, .NET, Smalltalk et similia gestiscono direttamente la memoria eliminando i puntatori e la allocazione/deallocazione esplicita. Quindi l’uso di questi ambienti semplifica la vita ai programmatori e ai tester, fa produrre codice migliore, rende i programmi meno costosi. Alla fine questi vantaggi ricadono sugli utenti.

Premesso questo io penso che i miglioramenti sarebbero evidenti anche a prezzo di un notevole rallentamento.

Ma questo notevole rallentamento non accade.

Java, .NET e anche alcune implementazioni di Smalltalk hanno dei sistemi di ottimizzazione del runtime. In particolare Java e .NET sfruttano dei compilatori JIT (Just In Time). I JIT analizzano il codice in esecuzione e lo compilano in codice nativo (vuol dire che su un Windows Vista a 32 bit viene generato codice per il processore x86). Questo accade durante l’esecuzione del programma. In altri termini se il programma rimane in memoria viene compilato man mano che viene eseguito (Just In Time appunto). Il trade-off quando questo accade è di solito una maggiore occupazione di memoria. E’ ovvio che se si scarica un programma (cioè se ne termina l’esecuzione) spesso, il JIT non ha modo di manifestare adeguatamente la sua presenza. Inoltre alcuni ambienti permettono persino di precompilare un programma e di memorizzare il codice in una cache o in un eseguibile. In questo modo il JIT è eseguito a priori come un normale compilatore. In .NET esiste un comando dell’SDK denominato NGEN che serve a questo. Infine si noti che .NET è usato anche per scrivere videogiochi sulla XBOX ed esistono implementazioni real-time di Java (J9 di IBM).

Parlare quindi oggi di lentezza delle VM è abbastanza fuori luogo, soprattutto in un momento in cui stanno anche tornando di moda i linguaggi dinamici. Chi è ancora ancorato al passato ne prenda finalmente atto e cominci ad agire di conseguenza. 

4 comments
  1. Diego said:

    Dopo esser stato citato (sono il socio di cui sopra), non posso esimermi dal postare un mio modesto commento.
    Spesso il “bravo programmatore” si dimentica che quello che sviluppa non è una torre d’avorio, bensì un elemento che andrà ad interagire con un ecosistema di altri software (e, spesso, hardware) che ne determineranno il corretto funzionamento. Sistemi esterni all’applicazione quali un database oppure la rete sono sicuramente molto più “lenti” del codice di business dell’applicazione e quindi benchmark dove si dimostra che un loop in un determinato linguaggio impiega qualche nanosecondo in meno di un altro mi pare ridicolo. A meno che non siate programmatori del CERN!
    Concludo ricordando pure che la “velocità” di cui spesso si parla per i programmi client è in realtà la reattività, ovvero la percezione di una pronta risposta del programma agli occhi dell’utente finale. Quando quest’ultimo clicca su un tasto non è bene che passi più di mezzo secondo prima che il vs programma reagisca in un qualsiasi modo; sottolineo il “qualsiasi” perché può benissimo essere una finestra con la storica frase “attendere prego”…
    magari in caratteri 3D via WPF🙂

  2. sirus said:

    Sebbene non sia ancora entrato appieno in possesso della capacità di programmare in Java e .NET non posso che sostenere quanto viene detto in questo articolo.
    Io stesso sostengo che in molti casi Java (giusto per citare il più diffuso dei linguaggi di programmazione basati su VM) non sia la scelta migliore (eg. la lentezza percepibile di NeoOffice per Mac OS X, oppure l’enorme perso di Azureus client BitTorrent) tuttavia la vita del programmatore viene in generale semplificata di molto.

    La mia opinione è che Java come altri linguaggi VM-based sono la cosa migliore in moltissime situazioni, in altre linguaggi più standard come C/C++ possono ancora dire la loro, nonostante richiedano uno sforzo maggior al programmatore.

    Come si dice… “ad ognuno il suo!”.

  3. Max said:

    Per restare su Java il problema, come dice Diego, è la reattività. E la causa principale della bassa reattività di un programma Java è Swing. C’è una alternativa migliore: SWT.

    Ovviamente Windows Forms in .NET questo problema non l’ha, dato che utilizza il sistema di finestre di Windows direttamente. E WPF è ancora meglio visto che il disegno degli elementi è delegato alla GPU.

  4. Riccardo said:

    In .NET il sistema operativo dovrebbe essere in grado di condividere le dll degli assembly (comprese immagini native) tra più processi diversi che utilizzano .NET. Questo dovrebbe mitigare anche il problema dell’uso abbastanza pesante della RAM e i tempi di caricamento delle applicazioni nel caso che si utilizzino più processi .NET sulla macchina.

    Questo tuo post mi ricorda questo (http://www.joelonsoftware.com/articles/fog0000000245.html) articolo di Joel Spolsky dove si parla di Lotus 123 vs Excel. Il problema non è proprio lo stesso ma fa capire bene che scelte corrette sulle strategie di sviluppo possono dare ottimi risultati.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: