SXXXXXXX_ProfileAnalyzer/doc/Italian-manual.md
2025-06-23 14:42:47 +02:00

138 lines
7.9 KiB
Markdown

## 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:
1. **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.
2. **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.
3. **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.
### 3. Flussi di Lavoro Principali
#### A. Eseguire il Profiling di un Nuovo Script
Questo è il modo più comune per iniziare.
1. Clicca su **"Profile a Script..."**. Si aprirà la finestra "Launch Profile Manager".
2. Clicca su **"New"** per creare un nuovo profilo.
3. **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 `.py` da 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`).
4. Clicca su **"Save Changes"**.
5. Il tuo nuovo profilo apparirà nella lista a sinistra. Selezionalo e clicca **"Run & Profile Selected"**.
6. 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.
1. Clicca su **"Load Profile File..."**.
2. Seleziona il tuo file `.prof` dalla finestra di dialogo.
3. 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:
```python
# 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` (o `tottime`) è il tempo speso *all'interno* di una funzione, escludendo il tempo speso nelle funzioni che essa chiama.
* **Risultato Atteso**: Vedrai `time.sleep` o una funzione simile in cima, con un `tottime` di circa 2 secondi. Subito dopo, vedrai `expensive_calculation`, ma con un `tottime` molto basso, perché quasi tutto il suo tempo è stato speso in `time.sleep`. Questo ti dice che `expensive_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` (o `cumtime`) è 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_data` sarà in cima alla lista con un `cumtime` di poco superiore a 2 secondi. Il suo `tottime` sarà basso, ma il `cumtime` alto 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_function` apparirà in cima con 1000 chiamate. Selezionandola, vedrai che il suo `tottime` e `cumtime` sono 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_data` a `expensive_calculation`, e da lì a `time.sleep`. Il nodo `time.sleep` sarà rosso vivo, indicando chiaramente che è la fonte del rallentamento. Vedrai anche una freccia da `process_data` a `utility_function` con 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**:
1. Assicurati di aver installato il software **Graphviz** (non solo la libreria Python).
2. Assicurati che la cartella `bin` di Graphviz sia nel `PATH` del tuo sistema.
3. Assicurati di aver installato la libreria `Pillow` (`pip install Pillow`).
4. 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.