lezione 08

performance e profiling

misura, ottimizza e scala: workflow completo per codice veloce.

livello: avanzato durata: 50 min output: benchmark affidabili badge: performance

profiling prima di ottimizzare

ottimizzare senza misurare crea regressioni. identifica il collo di bottiglia con dati reali e un carico rappresentativo, poi intervieni in modo mirato.

regola: misura, cambia una cosa, misura di nuovo.

flag di compilazione

# debug + simboli
clang++ -std=c++20 -O0 -g main.cpp -o app

# release
clang++ -std=c++20 -O2 -march=native main.cpp -o app

usa -O2 per release, -O3 solo se hai benchmark che mostrano benefici reali.

benchmark stabili

tieni il codice fuori da I/O e usa std::chrono con loop ripetuti.

#include <chrono>

auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 100000; ++i) {
    compute();
}
auto end = std::chrono::high_resolution_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

ripeti 5-10 volte e scarta i valori estremi per una media pulita.

allocazioni e move

  • usa reserve su vector per evitare riallocazioni.
  • preferisci passaggio per riferimento costante.
  • sfrutta move semantics per evitare copie pesanti.
std::vector<int> values;
values.reserve(1024);

std::string payload = build();
std::string moved = std::move(payload);

località dati

strutture compatte e accessi sequenziali sono più veloci della logica complessa.

scelta impatto
array of struct migliore per accesso lineare ai record
struct of arrays migliore per vettorizzazione e cache

strumenti

  • perf o Instruments per il profilo cpu.
  • valgrind o heaptrack per memoria.
  • sanitizers (-fsanitize=address) per bug nascosti.

checklist finale

  • benchmark replicabili con input reale.
  • ottimizza solo le funzioni nel top 5% di costo.
  • riduci allocazioni e copia dati il meno possibile.
  • verifica sempre con sanitizers dopo i cambiamenti.

panoramica

In questo capitolo su performance e profiling, misura, ottimizza e scala: workflow completo per codice veloce. L'obiettivo è trasformare i concetti in micro-pattern riutilizzabili con esempi piccoli e verificabili.

Lavora in sequenza: leggi, prova, modifica gli snippet e annota i trade-off principali (performance, leggibilità, manutenzione).

badge: performance

obiettivi

  • capire e applicare profiling prima in uno scenario reale
  • capire e applicare flag di compilazione in uno scenario reale
  • capire e applicare benchmark stabili in uno scenario reale
  • capire e applicare allocazioni e move in uno scenario reale

scheda rapida

#include <iostream>
#include <vector>

int main() {
  std::vector<int> dati{1, 2, 3};
  for (auto &v : dati) {
    v *= 2;
  }
  for (const auto &v : dati) {
    std::cout << v << " ";
  }
  std::cout << "\n";
  return 0;
}

Adatta questo scheletro agli esempi della lezione e sostituisci i dati con il tuo dominio.

tips

  • compila con warning elevati
  • preferisci RAII
  • usa const ovunque possibile
  • misura prima di ottimizzare
  • usa -O2/-O3
  • riduci allocazioni in loop

tip: Ottimizzare senza misure è solo ipotesi.

mini progetto

Confronta due approcci di calcolo.

  • implementa due varianti
  • misura il tempo
  • ripeti più volte
  • annota differenze

output atteso: uno script o query ripetibile con risultati verificabili.

start a brief