# Ottimizzazione (informatica)

In informatica, l'ottimizzazione è il processo atto a modificare alcuni aspetti di un sistema per lavorare più efficientemente o per utilizzare meno risorse. Ad esempio, un programma per computer può essere ottimizzato in modo che venga eseguito più velocemente o in modo da richiedere meno memoria o consumare meno energia della batteria. Il sistema può essere un singolo programma, un insieme di computer o un'intera rete come Internet.
Anche se la parola "ottimizzazione" condivide la stessa base di "ottimo", è raro che il processo di ottimizzazione produca un sistema ottimo. Il sistema ottimizzato sarà tipicamente ottimo solamente in un senso. Si può ridurre il tempo di esecuzione di un programma, ma al prezzo di consumare più memoria; oppure un programma può occupare meno memoria, ma al prezzo della velocità di esecuzione. Non esiste una soluzione che "metta d'accordo tutti", cosicché il programmatore dovrà sapere quale strada perseguire. In più, il tentativo atto a rendere ottimo una parte del software è di solito più dispendioso rispetto ai benefici che si può ottenere. In questo modo il processo di ottimizzazione può essere saltato prima di trovare una soluzione completamente ottimale. Fortunatamente i più grandi miglioramenti arrivano sempre prima di questo processo.
L'ottimizzazione può essere a più livelli. Al livello più alto il progetto può essere ottimizzato per sfruttare al meglio le risorse. L'implementazione può essere fatta mediante algoritmi efficienti e la scrittura di questi algoritmi beneficerà da quella di codice di buona qualità. L'uso di un compilatore con ottimizzatore aiuta a generare un programma eseguibile ottimizzato. Al livello più basso è possibile scrivere codice Assembly direttamente a mano. Con i compilatori moderni e la crescente complessità dei processori, occorrono grandi abilità a scrivere codice assembly che è migliore di quello del compilatore. L'ottimizzazione di solito viene fatta in casi speciali e il codice può essere più difficile da leggere e può contenere più errori rispetto al codice non ottimizzato.

## Esempio

I processi di calcolo possono essere scritti in diversi modi, con efficienze variabili. L'esempio seguente, un programma in C che somma tutti gli interi da 1 a N:
Lo stesso codice può essere scritto così:
L'ottimizzazione, spesso fatta automaticamente, è quella di prendere un metodo che è computazionalmente più efficiente mantenendo la stessa funzionalità.
L'ottimizzazione non è sempre un processo ovvio e intuitivo. Nell'esempio precedente, la versione 'ottimizzata' potrebbe essere più lenta se N è sufficientemente basso e il processore è più veloce ad eseguire le addizioni e i cicli rispetto alle moltiplicazioni e alle divisioni.

## Compromessi

L'ottimizzazione si concentra sul miglioramento di uno o più aspetti: tempo di esecuzione, utilizzo di memoria, banda, spazio del disco, consumo di energie ed altro. Questo provoca quel fenomeno detto compromesso: si ottimizza un aspetto alle spese degli altri. Ad esempio, aumentando la dimensione della cache migliorano le prestazioni in tempo di esecuzione, ma si aumenterà anche il consumo di memoria.
Ci sono dei casi in cui il programmatore, effettuando l'ottimizzazione, deve decidere di rendere il software ottimo per alcune operazioni al prezzo di altre meno efficienti. Questi compromessi possono essere di natura non tecnica, come quando un concorrente pubblica un grafico di prestazioni che deve essere superato per ottenere successo commerciale, ma al prezzo di rendere l'uso del software meno efficiente. Questi cambiamenti sono detti di solito come pessimizzazioni (in inglese: pessimizations).

## Ambiti

In ricerca operativa, l'ottimizzazione è il problema di determinare i valori d'ingresso di una funzione che minimizza o massimizza il suo valore. Di solito dei vincoli sono imposti sui valori che la funzione può ottenere; questo problema è noto come ottimizzazione dei vincoli.
In informatica, l'ottimizzazione implica la modifica del codice e dei parametri di compilazione per produrre un software più efficiente.
I problemi più comuni hanno di solito un grande numero di alternative che possono essere scelte dal programmatore.

## Colli di bottiglia

L'ottimizzazione è seguita dalla ricerca di un collo di bottiglia: la parte critica del codice che è la prima consumatrice delle risorse. Di solito tale collo di bottiglia rappresenta il 20% del codice, ma è responsabile dell'80% dei risultati (vedere anche Principio di Pareto).
Il Principio di Pareto (noto anche come regola 80-20) dichiara che per molti fenomeni l'80% delle conseguenze dipende dal 20% delle cause.
Il progetto dell'architettura di un sistema influisce molto sulle prestazioni. La scelta di un algoritmo è più importante di ogni altro elemento del progetto.
In alcuni casi, aggiungere più memoria può aiutare un programma a funzionare più velocemente. Ad esempio, un programma di filtro di solito legge ogni riga e filtra immediatamente l'output. Questo utilizza la memoria solo per una riga, ma le prestazioni sono tipicamente scarse. Queste possono essere migliorate leggendo l'intero file e scrivere poi il risultato, anche se ciò richiede più memoria.

## Quando ottimizzare?

L'ottimizzazione può ridurre la leggibilità e aggiungere codice utilizzato solo per migliorare le prestazioni. Questo può complicare programmi e sistemi, rendendoli più difficili da leggere e per fare debug. Come risultato, l'ottimizzazione o l'aggiustamento delle prestazioni viene fatto di solito alla fine del processo dello sviluppo.
Donald Knuth disse, parafrasando Hoare,
* "Possiamo dimenticarci quelle piccole efficienze, per il 97% del tempo: l'ottimizzazione prematura è la radice di tutti i mali."
Charles Cook commentò,
* "Sono d'accordo. Di solito non vale la pena di spendere un sacco di tempo a "micro-ottimizzare" codice prima di scoprire dove siano i colli di bottiglia. Ma quando si progetta software al livello di sistema, i problemi delle prestazioni devono essere sempre considerati sin dall'inizio. Un buon programmatore farà questo automaticamente, avendo l'esperienza sufficiente a scoprire i punti più critici. Un programmatore inesperto non si preoccuperà di questo, pensando che un po' di aggiustamento alla fine risolverà tutti i problemi."
L'"ottimizzazione prematura" è una frase, utilizzata per descrivere la situazione di un programmatore che permette che le considerazioni sulle prestazioni possono influire sul progetto di un pezzo di codice. Questo può produrre un progetto che non è così chiaro come doveva essere o codice che non è corretto, perché il codice è diventato più complicato a causa dell'ottimizzazione.
Un approccio alternativo è quello di progettare prima, fare codice dal progetto e quindi fare controlli di prestazioni sul codice per vedere se deve essere ottimizzato. Un progetto semplice ed elegante è più facile da ottimizzare in questa fase.
In pratica, è bene tenere in mente gli obiettivi di prestazioni in mente quando si progetta il software, ma il programmatore bilancia gli obiettivi di progettazioni e dell'ottimizzazione.

### Linguaggi interpretati

Nei linguaggi interpretati (specialmente quelli che vengono eseguiti ripetutamente come PHP e JavaScript) alcuni programmatori tolgono commenti, spazi e metodi o funzioni inutilizzati dai programmi prima di metterli in produzione.
Se il programmatore toglie i commenti e la formattazione del codice, sacrifica la leggibilità del codice. Diventa più difficile per un umano leggere, fare il debug e di conseguenza modificare o estendere il codice.

## Aforismi

* “La prima regola dell'ottimizzazione dei programmi è: non farlo. La seconda regola dell'ottimizzazione dei programmi (solo per esperti!) è: non farlo, ancora!” - Michael A. Jackson.
* “L'ordine nel quale le operazioni vengono eseguite in ogni particolare caso è una questione molto interessante e curiosa, nella quale il nostro spazio non ci permette di comprendere completamente. In quasi ogni calcolo, è possibile effettuare una serie di aggiustamenti in ogni fase e varie considerazioni devono influenzare la scelta per gli scopi di un motore di calcolo. Un obiettivo essenziale è quello di scegliere quella combinazione che potrebbe ridurre al minimo il tempo necessario al calcolo.” - Note di Ada Byron sul motore analitico, 1842.
* "In informatica, in nome dell'efficienza vengono commessi sempre più peccati (senza necessariamente ottenerla), piuttosto che per altri motivi, compresa la bieca stupidità.” - W.A. Wulf.
* “Possiamo dimenticarci quelle piccole efficienze, per il 97% del tempo: l'ottimizzazione prematura è la radice di tutti i mali. Non dobbiamo sprecare il tempo nemmeno per quel 3% di codice critico.” - Knuth, parafrasando Hoare.
* “I colli di bottiglia avvengono nei luoghi più incredibili. Quindi non provare ad inserire un trucco per velocizzare se non sai dov'è il collo di bottiglia.” - Rob Pike.

## Esperienza utente

L'ottimizzazione va a impattare sull'esperienza utente, in quanto un programma meno ottimizzato, richiederà più tempo per la sua esecuzione e di conseguenza sarà anche tendenzialmente meno reattivo, Julio Merino in forze a Snowflake (ex Microsoft ed ex Google), ha ironicamente confrontato le prestazioni di programmi tra un sistema d'annata con Windows NT 3.51 rispetto ai sistemi moderni, constatando come l'esperienza d'uso sia con il tempo drasticamente degradata.
Espediente utilizzato per constatare come le applicazioni odierne (secondo decennio del terzo millennio) siano decisamente poco ottimizzate, accusando come le applicazioni siano diventate sempre più pesanti e complesse (funzionalità, grafica avanzata, effetti visivi, connettività di rete e integrazioni con altri servizi), il tutto richiede più tempo per caricare le risorse e dipendenze necessarie per l'esecuzione delle applicazioni.
Inoltre anche i sistemi operativi moderni tendono sempre più ad avviare una serie di servizi e processi in background per le funzionalità aggiuntive e supporto per le applicazioni, occupando tempo e risorse, inficiando la velocità delle applicazioni.
Allo stesso modo i timori riguardo la sicurezza sono aumentate nel corso degli anni, impattando nella velocità di avvio delle applicazioni, che devono spesso eseguire controlli di sicurezza molto più articolati, quale la verifica dell'integrità del software, l'autenticazione degli utenti e il controllo degli accessi. Il tutto aggravato da pessime abitudini nell'uso di utilizzare un framework applicativo "preconfezionato", caricano dozzine di librerie con le rispettive dipendenze (sfruttate sì e no per il 5% del totale), appesantendo inutilmente i programmi.
Dave Cutler, padre di Windows NT era ossessione dalle prestazioni, in quanto convinto che un sistema operativo veloce e reattivo potesse assicurare una migliore esperienza per gli utenti, favorendo così l'adozione del sistema operativo da parte dei clienti e delle aziende, per far ciò era determinato a ottimizzare e migliorare le prestazioni, rendendolo efficiente e veloce, lavorando a stretto contatto con il team di sviluppo, ottimizzando il codice, migliorando gli algoritmi e cercando di ridurre al minimo i tempi di risposta del sistema.
Con il passare degli anni le priorità si sono modificate, il che ha impattato sull'esperienza d'uso, bisogna sottolineare che da Windows NT (sistema operativo leggero), ed anche le ridotte dimensioni dei programmi se paragonate ad oggi, sono fattori che hanno impattato sul confronto, ma una calcolatrice è sempre una calcolatrice.