7.9 KiB
Manuale Utente: Python Profile Analyzer (Italiano)
1. Introduzione
Benvenuto in Python Profile Analyzer! Questo strumento è progettato per rispondere a una delle domande più comuni nello sviluppo software: "Perché il mio codice è lento?".
Python Profile Analyzer ti permette di eseguire il tuo codice sotto il profiler standard di Python, cProfile, e di analizzare i risultati attraverso un'interfaccia grafica intuitiva. Invece di leggere file di testo complessi, potrai navigare tra i dati, ordinare, filtrare e visualizzare le interazioni tra le funzioni per identificare rapidamente i colli di bottiglia e ottimizzare le performance della tua applicazione.
2. Panoramica dell'Interfaccia
L'interfaccia è divisa in tre aree principali:
-
Barra degli Strumenti Superiore:
- Load Profile File...: Carica un file di dati di profiling (
.prof) già esistente. - Profile a Script...: Apre il Gestore Profili per configurare ed eseguire il profiling di un nuovo script o modulo.
- Export to CSV...: Esporta i dati attualmente visualizzati nella tabella in un file CSV.
- Current Profile: Mostra il nome del file di profilo attualmente caricato.
- Load Profile File...: Carica un file di dati di profiling (
-
Pannello delle Statistiche Principali:
- È un'area a schede (tab) che fornisce diverse viste sui dati:
- Table View: La vista principale. Una tabella interattiva con le statistiche di ogni funzione.
- Text View: L'output testuale standard di
pstats, utile per una visione d'insieme. - Graph View: (Disponibile solo se Graphviz è installato) Una visualizzazione a grafo delle chiamate.
- Controlli (sotto le schede): Permettono di ordinare e filtrare i dati visualizzati nella tabella e nella vista testuale.
- È un'area a schede (tab) che fornisce diverse viste sui dati:
-
Pannello dei Dettagli (in basso):
- Quando selezioni una funzione nella Table View, questi due pannelli si popolano automaticamente:
- Callers: Mostra quali funzioni hanno chiamato la funzione selezionata.
- Callees: Mostra quali funzioni sono state chiamate dalla funzione selezionata.
- Quando selezioni una funzione nella Table View, questi due pannelli si popolano automaticamente:
3. Flussi di Lavoro Principali
A. Eseguire il Profiling di un Nuovo Script
Questo è il modo più comune per iniziare.
- Clicca su "Profile a Script...". Si aprirà la finestra "Launch Profile Manager".
- Clicca su "New" per creare un nuovo profilo.
- Compila i dettagli del profilo:
- Profile Name: Un nome descrittivo (es. "Mio Script di Test").
- Run as Module: Seleziona questa opzione se vuoi lanciare un modulo (es.
python -m mio_modulo). - Script Path (se non è un modulo): Clicca
...per selezionare il file.pyda eseguire. - Project Root Folder (se è un modulo): Clicca
...per selezionare la cartella radice del tuo progetto. - Module Name (se è un modulo): Inserisci il nome del modulo da lanciare (es.
mio_modulo.main). - Arguments: Inserisci eventuali argomenti da passare allo script (es.
--input file.txt --verbose).
- Clicca su "Save Changes".
- Il tuo nuovo profilo apparirà nella lista a sinistra. Selezionalo e clicca "Run & Profile Selected".
- L'applicazione eseguirà lo script in background. Al termine, i risultati verranno automaticamente caricati e visualizzati.
B. Caricare un File di Profilo Esistente
Se hai già un file di dati (.prof) generato in precedenza (anche da cProfile da riga di comando), puoi analizzarlo.
- Clicca su "Load Profile File...".
- Seleziona il tuo file
.profdalla finestra di dialogo. - I dati verranno caricati e visualizzati nell'interfaccia.
4. Analisi dei Risultati: Un Caso d'Uso
Comprendere i dati è la chiave. Immaginiamo di avere il seguente script slow_script.py da analizzare:
# slow_script.py
import time
def utility_function(n):
# Funzione veloce, ma chiamata molte volte
return n * 2
def expensive_calculation():
# Funzione intrinsecamente lenta
print("Doing expensive calculation...")
time.sleep(2) # Simula un calcolo pesante
print("...done.")
def process_data():
# Funzione che orchestra altre chiamate
print("Processing data...")
total = 0
for i in range(1000):
total += utility_function(i)
expensive_calculation()
print(f"Final total: {total}")
if __name__ == "__main__":
process_data()
Dopo aver eseguito il profiling di questo script, ecco come interpretare i risultati.
Passo 1: Qual è la funzione più lenta in assoluto?
Vai alla Table View e clicca sull'header della colonna "Total Time (s)" per ordinare in modo decrescente.
- Cosa cercare: La funzione in cima alla lista.
Total Time(otottime) è il tempo speso all'interno di una funzione, escludendo il tempo speso nelle funzioni che essa chiama. - Risultato Atteso: Vedrai
time.sleepo una funzione simile in cima, con untottimedi circa 2 secondi. Subito dopo, vedraiexpensive_calculation, ma con untottimemolto basso, perché quasi tutto il suo tempo è stato speso intime.sleep. Questo ti dice cheexpensive_calculationè lenta a causa di una specifica operazione al suo interno.
Passo 2: Quale funzione è un collo di bottiglia a causa delle funzioni che chiama?
Ora, ordina per "Cum. Time (s)" (Tempo Cumulativo).
- Cosa cercare:
Cumulative Time(ocumtime) è il tempo totale speso in una funzione, incluso il tempo speso in tutte le sotto-chiamate. È utile per trovare le funzioni "manager" che sono lente a causa del lavoro che delegano. - Risultato Atteso:
process_datasarà in cima alla lista con uncumtimedi poco superiore a 2 secondi. Il suotottimesarà basso, ma ilcumtimealto ci dice che è il punto di partenza del nostro collo di bottiglia.
Passo 3: C'è una funzione che viene chiamata troppe volte?
Ordina per "N-Calls" (Numero di Chiamate).
- Cosa cercare: Funzioni con un numero di chiamate eccezionalmente alto. Anche una funzione veloce, se chiamata milioni di volte, può causare un rallentamento a causa dell'overhead.
- Risultato Atteso:
utility_functionapparirà in cima con 1000 chiamate. Selezionandola, vedrai che il suotottimeecumtimesono molto bassi, quindi in questo caso non è un problema. Ma se lo fossero, avresti trovato un candidato per l'ottimizzazione (es. vettorizzazione).
Passo 4: Come posso visualizzare il flusso di esecuzione?
Passa alla scheda Graph View.
- Cosa cercare: Il "percorso caldo" (hot path). I nodi (funzioni) sono colorati da verde (veloce) a rosso (lento) in base al loro
tottime. Le frecce indicano il flusso delle chiamate. - Risultato Atteso: Vedrai un percorso che va da
process_dataaexpensive_calculation, e da lì atime.sleep. Il nodotime.sleepsarà rosso vivo, indicando chiaramente che è la fonte del rallentamento. Vedrai anche una freccia daprocess_dataautility_functioncon l'etichetta "1000 calls". - Consiglio: Usa lo slider "Node Threshold" per filtrare le funzioni poco significative e ridurre il rumore nei grafi complessi.
Passo 5: Chi chiama questa funzione lenta e cosa chiama?
Torna alla Table View e seleziona la riga di expensive_calculation.
- Guarda il pannello Callers: Vedrai che è stata chiamata da
process_data. - Guarda il pannello Callees: Vedrai che ha chiamato
time.sleep.
Questo conferma il contesto della chiamata, aiutandoti a capire dove e perché una funzione viene eseguita.
5. Risoluzione dei Problemi
- La "Graph View" è disabilitata o grigia:
- Assicurati di aver installato il software Graphviz (non solo la libreria Python).
- Assicurati che la cartella
bindi Graphviz sia nelPATHdel tuo sistema. - Assicurati di aver installato la libreria
Pillow(pip install Pillow). - Dopo aver caricato un profilo, un grafo iniziale viene generato automaticamente. Se non vedi nulla, prova a cliccare "Generate Graph" o a ridurre la soglia.