2013-06-14 10 views
9

sto sperimentando quello che credo sia una perdita di memoria quando si utilizza l'API MySQLdbPerdita di memoria con ampio set di dati quando si utilizza mysql-python

Line # Mem usage Increment Line Contents 
================================================ 
    6        @profile 
    7 10.102 MB  0.000 MB def main(): 
    8 10.105 MB  0.004 MB  connection = MySQLdb.connect(host="localhost", db="mydb", 
    9 11.285 MB  1.180 MB         user="notroot", passwd="Admin123", use_unicode=True) 
    10 11.285 MB  0.000 MB  cursor = connection.cursor(cursorclass=MySQLdb.cursors.SSCursor) 
    11         
    12 11.289 MB  0.004 MB  cursor.execute("select * from a big table;") 
    13         
    14 254.078 MB 242.789 MB  results = [result for result in cursor] 
    15 251.672 MB -2.406 MB  del results 
    16 251.672 MB  0.000 MB  return 

Anche quando esplorare il cumulo con guppy/hpy dimostra che la maggior parte della mia la memoria è occupata da oggetti unicode, interi e oggetti datetime (molto probabilmente per le righe restituite dall'API MySQLdb).

Sto usando Python 2.7.3, mysql-python==1.2.4 su Ubuntu 12.04 e profilato con memory_profiler.

Potrebbe essere internato come descritto in http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm?

Sono mancante di riferimenti in giro?

EDIT: Ho anche chiuso il cursore e la connessione, ma ho comunque ottenuto risultati simili.

RISOLTO: Facepalm. Stavo facendo una lista di comprensione con naturalmente tenuto tutto in memoria. Quando si consuma l'iteratore correttamente (streaming su un file o qualcosa) ha un uso discreto della memoria.

Line # Mem usage Increment Line Contents 
================================================ 
    16        @profile 
    17 10.055 MB  0.000 MB def main(): 
    18 10.059 MB  0.004 MB  connection = MySQLdb.connect(host="localhost", db="mydb", 
    19 11.242 MB  1.184 MB         user="notroot", passwd="Admin123", use_unicode=True) 
    20 11.242 MB  0.000 MB  cursor = connection.cursor(cursorclass=MySQLdb.cursors.SSCursor) 
    21         
    22 11.246 MB  0.004 MB  cursor.execute("select * from big table") 
    23 11.246 MB  0.000 MB  count = 0 
    24 30.887 MB 19.641 MB  for result in cursor: 
    25 30.887 MB  0.000 MB   count = count + 1 
    26 30.895 MB  0.008 MB  cursor.close() 
    27 30.898 MB  0.004 MB  connection.close() 
    28 30.898 MB  0.000 MB  return 
+0

Cosa succede quando si cancella il cursore? Chiudi la connessione? Mi sembra che mi stia nascondendo la cache. Suggerimento: non usare '[foo for foo in bar]' quando un semplice 'list (bar)' farà. –

+2

Inoltre, il sistema operativo non rilascia memoria * immediatamente *. La memoria rimane assegnata a Python nel caso in cui il processo lo richieda nuovamente, viene rimosso dal processo solo se è necessario altrove. Solo perché la memoria deallizzata da python fa ** non ** significa che il sistema operativo immediatamente la recupera. –

+0

Ho dimenticato di chiudere il cursore e la connessione, ma anche dopo averlo fatto, non libererà ancora la memoria –

risposta

1

Risolto dall'OP. Il suo codice originale conteneva la linea

results = [result for result in cursor] 

La lista di comprensione memorizzato l'intero risultato in memoria, piuttosto che in streaming dal server in base alle esigenze. L'OP lo ha sostituito con un semplice

for result in cursor: 
    ... 

e ha visto il suo utilizzo della memoria tornare alla normalità.

Problemi correlati