Usa Claude Code per le indagini sulle prestazioni con un loop ripetibile: misura, formula un'ipotesi, cambia poco e rimisura prima di spedire.

I bug delle prestazioni invitano a fare supposizioni. Qualcuno nota che una pagina sembra lenta o che un'API va in timeout, e la mossa più rapida è "pulire" il codice, aggiungere cache o riscrivere un ciclo. Il problema è che "sembra lento" non è una metrica, e "più pulito" non è sempre uguale a più veloce.
Senza misurazione i team sprecano ore cambiando la cosa sbagliata. Il percorso critico potrebbe essere nel database, nella rete o in una singola allocazione inattesa, mentre il team lucida codice che incide poco sull'esecuzione. Peggio: una modifica che sembra intelligente può peggiorare le prestazioni: logging aggiuntivo in un ciclo stretto, una cache che aumenta la pressione di memoria, o lavoro parallelo che genera contesa sui lock.
L'indovinare rischia anche di rompere comportamenti. Quando cambi codice per velocizzarlo potresti alterare i risultati, la gestione degli errori, l'ordine o i retry. Se non ricontrolli correttezza e velocità insieme, puoi "vincere" un benchmark mentre passi in produzione un bug.
Tratta le prestazioni come un esperimento, non come un dibattito. Il loop è semplice e ripetibile:
Molte vittorie sono modeste: togliere l'8% dalla p95, ridurre la memoria di picco di 50 MB, o eliminare una query al database. Questi miglioramenti contano, ma solo se sono misurati, verificati e ripetibili.
Funziona meglio come loop, non come una richiesta una tantum di "rendilo più veloce". Il loop ti mantiene onesto perché ogni azione si ricollega a una prova e a un numero che puoi osservare.
Sequenza chiara:
Ogni passo ti protegge da un diverso tipo di autoinganno. Misurare prima ti evita di "riparare" qualcosa che non era il vero problema. Un'ipotesi scritta ti impedisce di cambiare cinque cose insieme e poi indovinare quale abbia inciso. Le modifiche minime riducono il rischio di rompere comportamenti o introdurre nuovi colli di bottiglia. Rimisurare cattura i falsi positivi (per esempio un run più veloce causato da cache calda) ed espone regressioni.
"Finito" non è una sensazione. È un risultato: la metrica obiettivo si è mossa nella direzione giusta e la modifica non ha causato regressioni evidenti (errori, più memoria, peggior p95 o endpoint più lenti).
Sapere quando fermarsi fa parte del flusso. Smetti quando i guadagni si appiattiscono, quando la metrica è già sufficientemente buona per gli utenti, o quando l'idea successiva richiede grandi refactor per un piccolo vantaggio. Il lavoro sulle prestazioni ha sempre costi opportunità; il loop ti aiuta a spendere tempo dove rende davvero.
Se misuri cinque cose insieme non saprai cosa è migliorato. Scegli una metrica primaria per questa indagine e tratta il resto come segnali di supporto. Per molti problemi user-facing la metrica è la latenza. Per lavoro batch può essere throughput, tempo CPU, uso memoria o anche costo cloud per esecuzione.
Sii specifico sullo scenario. "L'API è lenta" è troppo vago. "POST /checkout con un carrello tipico di 3 articoli" è misurabile. Mantieni gli input stabili così i numeri hanno senso.
Annota la baseline e i dettagli dell'ambiente prima di toccare il codice: dimensione del dataset, tipo di macchina, modalità di build, feature flag, concorrenza e warmup. Questa baseline è il tuo ancora. Senza di essa ogni cambiamento può sembrare progresso.
Per la latenza affidati alle percentili, non solo a una media. p50 mostra l'esperienza tipica, mentre p95 e p99 espongono la coda dolorosa di cui gli utenti si lamentano. Una modifica che migliora p50 ma peggiora p99 può comunque dare una sensazione di lentezza.
Decidi in anticipo cosa significa "significativo" così non ti accontenti del rumore:
Una volta stabilite queste regole, puoi testare idee senza spostare gli obiettivi.
Inizia con il segnale più semplice di cui ti puoi fidare. Un singolo timing intorno a una richiesta può dirti se hai un problema reale e quanto è grosso; conserva il profiling profondo per quando devi spiegare perché è lento.
Buone evidenze provengono spesso da una combinazione di fonti:
Usa metriche semplici quando la domanda è "è più lento e di quanto?" Usa il profiling quando la domanda è "dove va il tempo?" Se la p95 è raddoppiata dopo un deploy, parte da timing e log per confermare la regressione e circoscriverla. Se i timing mostrano che la maggior parte del ritardo è nel codice dell'app (non nel DB), allora un profiler CPU o un flame graph possono indicare la funzione esatta che è cresciuta.
Mantieni le misure sicure. Raccogli ciò che ti serve per fare debug delle prestazioni, non contenuti utente. Preferisci aggregati (durate, conteggi, dimensioni) ai payload raw e oscurare identificatori per default.
Il rumore è reale: prendi più campioni e annota gli outlier. Esegui la stessa richiesta 10–30 volte e registra mediana e p95 invece di usare una singola esecuzione migliore.
Scrivi la ricetta di test esatta così puoi ripeterla dopo le modifiche: ambiente, dataset, endpoint, dimensione del body, livello di concorrenza e come hai catturato i risultati.
Parti da un sintomo che puoi nominare: "la p95 sale da 220 ms a 900 ms durante i picchi", "la CPU è al 95% su due core" o "la memoria cresce di 200 MB all'ora". Sintomi vaghi come "sembra lento" portano a cambi casuali.
Poi traduci ciò che hai misurato in un'area sospetta. Un flame graph potrebbe mostrare molto tempo in JSON encoding, una trace potrebbe mostrare un percorso di chiamate lento, o le statistiche DB potrebbero mostrare una query che domina il tempo totale. Scegli l'area più piccola che spiega la maggior parte del costo: una funzione, una singola query SQL o una chiamata esterna.
Una buona ipotesi è una frase, testabile e legata a una previsione. Stai chiedendo di testare un'idea, non di far magicamente tutto più veloce.
Usa questo formato:
Esempio: "Perché il profilo mostra il 38% della CPU in SerializeResponse, allocare un nuovo buffer per richiesta sta causando picchi CPU. Se riusiamo un buffer, la p95 dovrebbe scendere di circa 10–20% e la CPU di ~15% sotto lo stesso carico."
Mantieniti onesto nominando alternative prima di toccare il codice. Forse la parte lenta è un dipendente upstream, contesa sui lock, un cambiamento nel miss rate della cache o un rollout che ha aumentato la dimensione del payload.
Scrivi 2–3 spiegazioni alternative, poi scegli quella supportata meglio dalle evidenze. Se la tua modifica non muove la metrica, hai già l'ipotesi successiva pronta.
Claude è più utile nel lavoro sulle prestazioni quando lo tratti come un analista attento, non come un oracolo. Mantieni ogni suggerimento ancorato a ciò che hai misurato e assicurati che ogni passo possa essere confutato.
Dagli input reali, non una descrizione vaga. Incolla piccole evidenze mirate: un sommario di profiling, alcune righe di log attorno alla richiesta lenta, un piano di query e il percorso di codice specifico. Includi i numeri "prima" (p95, tempo CPU, tempo DB) così sappia la tua baseline.
Chiedigli di spiegare cosa i dati suggeriscono e cosa non supportano. Poi forza spiegazioni concorrenti. Un prompt utile finisce con: "Dammi 2–3 ipotesi e per ciascuna dimmi cosa la falsificherebbe." Questo evita di fissarsi sulla prima storia plausibile.
Prima di cambiare qualcosa, chiedi il più piccolo esperimento che possa validare l'ipotesi principale. Fallo rapido e reversibile: aggiungi un timer attorno a una funzione, abilita una flag del profiler, o esegui una query DB con EXPLAIN.
Se vuoi una struttura compatta per l'output, chiedi:
Se non riesce a nominare una metrica, una posizione e un risultato atteso, sei tornato a indovinare.
Dopo avere evidenza e un'ipotesi, resisti alla tentazione di "pulire tutto". Il lavoro sulle prestazioni è più affidabile quando la modifica è piccola e facilmente annullabile.
Cambia una cosa alla volta. Se modifichi una query, aggiungi caching e refattorizzi un ciclo nello stesso commit, non saprai cosa ha aiutato (o danneggiato). Le modifiche a variabile singola rendono la misura successiva significativa.
Prima di toccare il codice, annota cosa ti aspetti in numeri. Esempio: "la p95 dovrebbe scendere da 420 ms a sotto 300 ms, e il tempo DB dovrebbe calare di ~100 ms." Se il risultato manca l'obiettivo, impari rapidamente che l'ipotesi era debole o incompleta.
Mantieni le modifiche reversibili:
"Minimo" non significa "banale." Significa concentrato: cache un risultato di funzione costosa, rimuovi un'allocazione ripetuta in un ciclo stretto o evita lavoro per richieste che non ne hanno bisogno.
Aggiungi un timing leggero attorno al collo di bottiglia sospettato così puoi vedere cosa è cambiato. Un singolo timestamp prima e dopo una chiamata (loggato o catturato come metrica) può confermare se la tua modifica ha colpito la parte lenta o ha solo spostato il tempo altrove.
Dopo una modifica, riesegui esattamente lo stesso scenario usato per la baseline: stessi input, ambiente e forma di carico. Se il test dipende da cache o warm-up, rendilo esplicito (per esempio: "prima esecuzione cold, successive 5 warm"). Altrimenti troverai miglioramenti che erano solo fortuna.
Confronta i risultati usando la stessa metrica e le stesse percentili. Le medie possono nascondere i problemi, quindi tieni d'occhio p95 e p99, oltre a throughput e tempo CPU. Esegui sufficienti ripetizioni per vedere se i numeri si stabilizzano.
Prima di festeggiare, controlla le regressioni che non si vedono in un numero principale:
Poi decidi basandoti sulle evidenze, non sulla speranza. Se il miglioramento è reale e non hai introdotto regressioni, mantieni la modifica. Se i risultati sono misti o rumorosi, revert e formula una nuova ipotesi, oppure isola ulteriormente la modifica.
Se lavori su una piattaforma come Koder.ai, prendere uno snapshot prima di sperimentare può rendere il rollback un singolo passo, facilitando test di idee più audaci in sicurezza.
Infine, annota ciò che hai imparato: la baseline, la modifica, i nuovi numeri e la conclusione. Questo breve record evita che il giro successivo ripeta gli stessi vicoli ciechi.
Il lavoro sulle prestazioni di solito devia quando perdi il filo tra ciò che hai misurato e ciò che hai cambiato. Mantieni una catena pulita di evidenze così puoi dire con fiducia cosa ha migliorato o peggiorato le cose.
I soliti colpevoli:
Un piccolo esempio: un endpoint sembra lento, quindi ottimizzi il serializer perché è caldo in un profilo. Poi ritesti con un dataset più piccolo e sembra più veloce. In produzione la p99 peggiora perché il database è ancora il collo di bottiglia e la tua modifica ha aumentato la dimensione del payload.
Se usi Claude Code per proporre fix, tienilo corto: chiedi 1–2 modifiche minime che corrispondano alle evidenze raccolte e insisti su un piano di re-misurazione prima di accettare una patch.
Le affermazioni di velocità si sfaldano quando il test è vago. Prima di festeggiare, assicurati di poter spiegare cosa hai misurato, come lo hai misurato e cosa hai cambiato.
Inizia nominando una metrica e scrivendo la baseline. Includi i dettagli che cambiano i numeri: tipo macchina, carico CPU, dimensione del dataset, modalità build (debug vs release), feature flag, stato della cache e concorrenza. Se non riesci a ricreare l'assetup domani, non hai una baseline.
Checklist:
Dopo che i numeri sono migliori, fai una veloce verifica di regressione. Controlla correttezza (stessi output), tasso di errori e timeouts. Osserva effetti collaterali come più memoria, picchi CPU, avvio più lento o maggiore carico DB. Una modifica che migliora la p95 ma raddoppia la memoria potrebbe essere un trade sbagliato.
Un team segnala che GET /orders va bene in dev ma rallenta in staging con carichi moderati. Gli utenti si lamentano di timeouts, ma la latenza media sembra "abbastanza OK", che è una trappola classica.
Prima, fissa una baseline. Con un load test stabile (stesso dataset, stessa concorrenza e durata) registri:
Raccogli evidenze. Una trace rapida mostra che l'endpoint esegue una query principale per gli ordini, poi itera e recupera gli item correlati per ordine. Noti anche che la risposta JSON è grande, ma il tempo DB domina.
Trasforma questo in una lista di ipotesi testabili:
Chiedi una modifica minima che corrisponda all'evidenza più forte: rimuovere una chiamata N+1 fetchando gli item in una singola query con chiave sugli order ID (o aggiungere l'indice mancante se il piano di esecuzione mostra una scansione completa). Mantienila reversibile e in un commit focalizzato.
Rimisura con lo stesso load test. Risultati:
Decisione: deploya la fix (vittoria chiara), poi avvia un secondo ciclo focalizzato sul gap residuo e sui picchi di CPU, dato che il DB non è più il principale limite.
Il modo più veloce per migliorare nelle indagini sulle prestazioni è trattare ogni run come un piccolo esperimento ripetibile. Quando il processo è consistente, i risultati diventano più affidabili da confrontare e condividere.
Un template di una pagina aiuta:
Decidi dove vivono queste note così non scompaiono. Un posto condiviso conta più dello strumento perfetto: una cartella nel repo accanto al servizio, un doc di team o note nel ticket. L'importante è la reperibilità. Qualcuno deve poter trovare "p95 spike dopo cambio cache" mesi dopo.
Rendi gli esperimenti sicuri un'abitudine. Usa snapshot e rollback facili così puoi provare un'idea senza paura. Se costruisci con Koder.ai, Planning Mode può essere un posto comodo per delineare il piano di misura, definire l'ipotesi e tenere la modifica scoping prima di generare un diff mirato e rimisurare.
Stabilisci una cadenza. Non aspettare gli incidenti. Aggiungi piccoli controlli di performance dopo cambi come query nuove, endpoint nuovi, payload più grandi o aggiornamenti di dipendenze. Un check di baseline di 10 minuti ora può risparmiarti una giornata di indovinare dopo.
Inizia con un numero che corrisponde al reclamo, di solito la latenza p95 per un endpoint e un input specifici. Registra una baseline nelle stesse condizioni (dimensione dei dati, concorrenza, cache fredda/calda), poi cambia una cosa e riesegui la misura.
Se non riesci a riprodurre la baseline, non stai ancora misurando: stai indovinando.
Una buona baseline include:
Annotala prima di toccare il codice così non sposti gli obiettivi.
Le percentili descrivono l'esperienza utente meglio di una media. p50 è il comportamento “tipico”, ma gli utenti si lamentano della coda lenta, cioè p95/p99.
Se p50 migliora ma p99 peggiora, il sistema può sembrare più lento anche se la media è migliore.
Usa timing semplici/log quando chiedi “è più lento e di quanto?” Usa il profiling quando chiedi “dove sta andando il tempo?”
Un flusso pratico: conferma la regressione con i timing delle richieste, poi profiler solo dopo aver confermato che il rallentamento è reale e circoscritto.
Scegli una metrica primaria e tratta il resto come guardrail. Un set comune è:
Questo ti evita di “vincere” un grafico mentre provochi timeouts, crescita di memoria o peggioramento della coda.
Scrivi un'ipotesi in una frase legata all'evidenza e a una previsione:
Se non puoi nominare evidenza e movimento atteso sulla metrica, l'ipotesi non è ancora testabile.
Rendila piccola, mirata e facile da annullare:
Piccoli diff rendono la misura successiva significativa e riducono il rischio di rompere il comportamento mentre insegui la velocità.
Riesegui lo stesso test (stessi input, ambiente e carico). Poi controlla regressioni oltre al numero principale:
Se i risultati sono rumorosi, prendi più campioni o revert e restringi l'esperimento.
Dagli evidenze concrete e costringilo a rimanere guidato dai test:
Se l'output non include metrica specifica e piano di re-test, stai tornando all'indovinare.
Ferma quando:
Il loop (misura → ipotesi → cambiamento → re-misura) ti aiuta a spendere tempo dove i numeri dimostrano che vale la pena.