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

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:

  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:

# 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.