Usa questi suggerimenti per analizzare il tuo codice e scoprire dove è più o meno efficiente.

Poiché "c'è più di un modo per farlo" in Python, trovare l'approccio più efficiente in termini di memoria per alcune attività può essere difficile. È qui che un profiler della memoria può aiutare. Oltre a tenere traccia delle perdite, la stima del profilo di memoria del codice aiuta a determinare quale codice è efficiente in termini di memoria.

Che tu stia sviluppando un modello di machine learning o un sito Web con Python, puoi stimare il profilo di memoria per script, singole righe di codice o funzioni.

La stima del profilo di memoria dell'intera base di codice potrebbe non essere pratica, in quanto ciò può rallentare notevolmente l'applicazione. È meglio profilare in modo selettivo funzioni o metodi che si sospetta possano invece consumare più memoria. Ma anche se vuoi farlo per l'intera applicazione, potresti voler dedicare un modulo isolato per gestirlo.

Esistono molte librerie di profilazione in Python. Alcuni dei più popolari sono

instagram viewer
memory_profiler, psutil, Tracemalloc, E pympler. Questo tutorial utilizza memory_profiler E psutil.

Mentre psutil è ideale per stimare il consumo totale di memoria di un metodo o dell'esecuzione di una funzione, memory_profiler fornisce informazioni più dettagliate sull'utilizzo della memoria, incluse le tendenze di utilizzo riga per riga e livello funzionale nel tempo.

Per iniziare, installa memory_profiler nel tuo ambiente virtuale Python. Anche questo si installa psutil.

pip installa memory_profiler

Ottieni la dimensione di un oggetto in memoria

È possibile avviare il profilo della memoria calcolando prima la dimensione di un oggetto che si intende utilizzare in memoria.

Questo tipo di creazione di profili è utile all'inizio dello sviluppo, durante il tentativo di determinare quale tipo di oggetto utilizzare in un programma.

Ad esempio, se rimani bloccato a decidere quali metodi utilizzare per raggiungere un compito, diciamo, l'appropriato Tipo di dati Python, puoi ottenere la dimensione di ciascuno in byte per determinare quale è più leggero per il tuo utilizzo caso.

IL sys.getsizeof metodo integrato è utile qui:

importare sys
stampa(f"dimensione elenco: {sys.getsizeof([])} byte")
stampa(f"dimensione del dizionario: {sys.getsizeof (dict)} byte")
stampa(f"dimensione tupla: {sys.getsizeof(())} byte")
stampa(f"imposta dimensione: {sys.getsizeof({})} byte")

Ecco l'output:

Puoi anche usare il sys.getsizeof metodo per confrontare la dimensione della memoria di una funzione incorporata e personalizzata.

Ad esempio, confronta questa funzione di lunghezza personalizzata con quella utilizza un ciclo Python for con l'integrato len funzione:

importare sys

defgetLunghezza(iterabile):
contare = 0

per io In iterabile:
contare +=1

ritorno contare

stampa(f"Funzione di lunghezza incorporata: {sys.getsizeof (len)} byte")
stampa(f"Funzione di lunghezza personalizzata: {sys.getsizeof (getLength)} byte")

Il codice sopra fornisce il seguente output:

Tuttavia, mentre sys.getsizeof misura la dimensione di un oggetto in memoria, tiene conto solo dell'oggetto stesso e non di quelli che vi fanno riferimento. Per questo, avrai bisogno di un metodo di profilazione più dettagliato.

Trova il profilo di memoria di una funzione Python

È possibile ottenere un profilo di memoria più dettagliato di ciascuna riga di codice di una funzione utilizzando il file memory_profiler pacchetto. Ciò comporta l'aggiunta di @profilo decoratore alla tua funzione o metodo:

importare panda
importa numpy
dal profilo di importazione memory_profiler

classe Manipolare:
@profilo
def manipolareDati (self):
df = panda. DataFrame({
'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
'B': [numpy.nan, "Pandas", numpy.nan, "Pandas", "Python", "JavaScript"],
})

df.fillna (metodo='bfill', inplace=True)
df.fillna (metodo='ffill', inplace=True)
ritorno str (df)

manip = Manipola()
stampa (manip.manipulateData())

Il codice sopra fornisce un profilo di memoria dettagliato di ogni riga di codice nella funzione come mostrato:

IL Utilizzo della memoria indica l'utilizzo della memoria per una particolare riga di codice, mentre la Incremento la colonna mostra l'overhead contribuito da ciascuna riga. IL Evento colonna definisce il numero di volte in cui una riga di codice alloca o dealloca la memoria.

Ad esempio, nell'output precedente, la riga 11 si è verificata due volte con un incremento di memoria di 0,1 MiB (Mebibyte), aumentando l'utilizzo della memoria a 55,4 MiB. Anche le linee 19 e 22 hanno contribuito rispettivamente con 0,2 MiB e 0,3 MiB, per un totale di 55,9 MiB di utilizzo della memoria.

Trova il profilo di memoria di uno script Python per timestamp

Puoi anche stimare il profilo di memoria di un intero script Python usando il memory_profiler eseguendo il mprof comando nel terminale come mostrato:

mprof esegue script_name.py

Il comando precedente campiona lo script specificato ogni 0,1 se crea automaticamente a .dat file all'interno della directory del progetto corrente.

Le figure che seguono il MEM notazione sono i profili di utilizzo della memoria dello script Python in un intervallo di tempo specifico. Le ultime cifre a destra rappresentano il timestamp acquisito dal profiler per ogni utilizzo della memoria.

Puoi anche ottenere un grafico del profilo di memoria. Ciò richiede l'installazione di matplotlib:

pip installa matplotlib

Una volta installato, esegui il file mprof comanda così:

trama mprof

Ecco l'output in questo caso:

Eseguire il profilo della memoria degli script in un file Python dedicato

Potresti voler creare un profilo per diversi script Python. Puoi farlo utilizzando un modulo Python dedicato tramite Python sottoprocesso.

In questo modo, puoi separare il tuo memory profiler dalla tua base di codice e salvare l'output del grafico localmente:

importare sottoprocesso

sottoprocesso.run([
'prof', 'correre', '--includi-bambini', 'mancante.py'
])

# salva l'output del grafico in locale
sottoprocesso.run(['prof', 'complotto', '--output=output.jpg'])

Per eseguire il profilo di memoria dello script, devi solo eseguire il file Python contenente il codice precedente. Questo genera un grafico del profilo di memoria (uscita.jpg) nella directory del file:

Trova la quantità di memoria utilizzata dall'esecuzione di una funzione

È possibile trovare il profilo di memoria totale di un metodo o di una funzione durante l'esecuzione utilizzando il file psutil pacchetto.

Ad esempio, per profilare il precedente Manipolazione di Pandas DataFrame metodo all'interno di un altro file Python:

importare psutil
importare sys
importare os
sys.path.append (sys.path[0] + "/..")

# importa la classe che contiene il tuo metodo
da codice.mancante importare Manipolare

# istanzia la classe
manip = Manipola()

processo = psutil. Processo (os.getpid())
initial_memory = process.memory_info().rss

# esegue il metodo target:
manip.manipulateData()

# ottiene le informazioni sulla memoria dopo l'esecuzione
final_memory = process.memory_info().rss
memory_consumed = final_memory - initial_memory
memoria_consumata_mb = memoria_consumata / (1024 * 1024)
stampa(f"Memoria consumata dalla funzione: {memoria_consumata_mb:.2F} MB")

Quanto sopra stima il profilo di memoria totale del metodo in megabyte (MB) come mostrato:

Trova il profilo di memoria di una riga di codice in Jupyter Notebook

Se usi iPython in Jupyter Notebook, puoi calcolare il profilo di memoria di un one-liner usando il file memory_profiler. Devi solo caricare memory_profiler in una cella. Quindi aggiungi il %memit funzione magica al tuo codice nelle celle successive; questo restituisce la memoria di picco del codice e la dimensione incrementata.

Questo metodo non funziona con i normali script Python oltre a iPython in Jupyter Notebook.

Per esempio:

Puoi anche usare il %memit funzione magica in Jypyter Notebook per profilare la memoria di una funzione in fase di esecuzione:

Migliora l'efficienza della tua memoria nel tuo codice Python

Considerando le pesanti attività di data lift per le quali usiamo spesso Python, ogni riga di codice necessita di un'adeguata ottimizzazione per gestire l'utilizzo della memoria. Sebbene Python presenti molte funzioni Python integrate, gli oggetti senza riferimenti provocano perdite di memoria.

Se hai eliminato ogni sintassi Python che funziona nella tua base di codice senza considerare l'utilizzo della memoria, potresti voler guardare indietro prima di andare troppo lontano.