Software moderno contro software di una volta: aprire un programma su un PC degli anni Novanta, magari emulato su hardware attuale, può lasciare a bocca aperta. Le finestre compaiono subito, i menu rispondono senza esitazioni, le interfacce reagiscono come se non ci fosse alcun ritardo. La sensazione, per chi ha vissuto quell’epoca e oggi la riscopre, è che i programmi di allora fossero semplicemente più rapidi. Eppure quei computer erano lenti, a volte lentissimi rispetto agli standard di oggi. Il punto è un altro, e riguarda il modo in cui il software veniva progettato.
Trent’anni fa gli sviluppatori lavoravano dentro limiti ferrei. Pochi megabyte di RAM, processori sotto i 100 MHz, dischi rigidi modesti e sistemi operativi che non potevano permettersi alcuno spreco. Proprio quei vincoli hanno plasmato la maniera di scrivere codice. La domanda che torna a circolare è semplice: perché macchine migliaia di volte più potenti sembrano offrire un’esperienza meno reattiva per cose banali come aprire un file o navigare tra le impostazioni?
Velocità percepita e velocità reale non coincidono
Un PC del 1995 montava magari un Pentium a 75 o 100 MHz, 8 o 16 MB di memoria e un disco IDE meccanico. Oggi un notebook qualsiasi ha CPU multicore, SSD NVMe e 16 GB di RAM. Ciononostante alcune applicazioni moderne impiegano secondi per operazioni che tecnicamente richiederebbero millisecondi.
Chi ha usato Lotus 1-2-3, Excel 2.0 o AutoCAD ricorda bene che certe operazioni pesanti richiedevano minuti interi. Ricostruire un foglio elettronico complesso poteva bloccare la macchina, compilare un programma significava aspettare. Le attività computazionalmente intense erano lente, su questo non ci piove. Ma l’interfaccia restava immediata. Aprire il menu Start, sfogliare una cartella, modificare un file di testo producevano una risposta quasi istantanea.
Il cuore della questione sta nella latenza di input, cioè il tempo che passa tra un clic, la pressione di un tasto e il primo aggiornamento visibile sullo schermo. Un software può eseguire milioni di operazioni al secondo e risultare comunque macchinoso, se aggiunge ritardi inutili tra un’azione e l’altra. La pressione di un tasto attraversa una catena lunga: firmware della tastiera, controller USB, polling HID, scheduler, coda eventi, compositore grafico, driver GPU, refresh del display. A 60 Hz un frame dura 16,6 ms, basta saltarne tre o quattro per trasformare una risposta teoricamente rapida in un ritardo che si vede.
Le vecchie interfacce testuali avevano un vantaggio brutale: spesso scrivevano direttamente nella memoria video. Aggiornare pochi caratteri voleva dire modificare celle in una schermata 80×25. Niente layout dinamico, niente animazioni, niente compositing con trasparenze. Non a caso Microsoft con Windows 11 ha introdotto il Low Latency Profile, che alza il clock del processore per un paio di secondi quando ci sono elaborazioni grafiche legate all’interfaccia da portare a termine.
Quando ogni kilobyte contava davvero
Negli anni Novanta misurare l’occupazione della memoria era la norma. Si riduceva l’attività sul disco, si ottimizzava il codice critico anche a livello assembler. Prodotti come WordPerfect o Turbo Pascal costruirono la propria reputazione sull’efficienza. La concorrenza era spietata e la velocità era una qualità che gli utenti percepivano subito.
Oggi la storia è diversa. Framework sempre più complessi, librerie esterne, componenti condivisi e telemetria aggiungono strati di elaborazione che passano inosservati in fase di sviluppo ma si fanno sentire nell’uso quotidiano. C’è una vecchia osservazione, la Legge di Wirth, secondo cui il software rallenta più in fretta di quanto l’hardware riesca ad accelerare. Formulata proprio in quegli anni, viene ancora citata perché descrive qualcosa che parecchi utenti riconoscono.
Con 640 KB di memoria convenzionale in MS-DOS ogni struttura dati pesava. Un programmatore non poteva caricare decine di librerie per comodità, doveva scegliere formati compatti e algoritmi prevedibili. Persino evitare copie inutili di stringhe faceva la differenza. Il software moderno, al contrario, tende ad accumulare dipendenze. Un’applicazione JavaScript può caricare migliaia di file tra pacchetti npm, polyfill, mappe sorgente e codice che non viene mai usato davvero. Il problema non è JavaScript in sé, il motore V8 ha un compilatore JIT avanzato. Il guaio nasce quando si usa un motore potente per compiti semplici, con troppi strati in mezzo.
Electron e il costo di portarsi dietro un browser
Un esempio citato spessissimo è quello delle applicazioni desktop costruite con Electron. Un programma all’apparenza nativo incorpora un’intera istanza di Chromium e del motore V8. Il vantaggio si vede: lo stesso codice gira su Windows, macOS e Linux. Il costo si misura invece in memoria occupata, tempo di avvio e consumo energetico.
Per aprire una chat, un editor minimale o un client di note il sistema può allocare centinaia di megabyte senza fare nulla di complesso. Chromium non è lento di suo, la sua architettura multiprocesso nasce per robustezza e sicurezza. Ma usarlo come toolkit desktop per ogni app sposta il costo di rendering e compatibilità anche dove non serve.
Il principio più efficace resta semplice: non fare all’avvio ciò che puoi fare dopo. Il primo frame deve arrivare presto, la finestra deve diventare interattiva prima di caricare plugin, modelli AI, cronologia remota e tour guidati. Conta ridurre il codice caricato, eliminare le librerie superflue, comprimere i contenuti statici e spostare le elaborazioni pesanti fuori dal thread dell’interfaccia, così da tenere tutto reattivo e fluido.