2012-05-15 14 views
11

Me enfrento al problema de las pérdidas de memoria usando pandas biblioteca en python. Creo objetos pandas.dataframe en mi clase y tengo un método que cambia el tamaño del marco de datos de acuerdo con mis condiciones. Después de cambiar el tamaño del marco de datos y crear un nuevo objeto pandas reescribo pandas.dataframe original en mi clase. Pero el uso de memoria es muy alto incluso después de una reducción significativa de la tabla inicial. Parte del código de ejemplo corto (que no he escrito gestor de procesos, veo administrador de tareas):Pandas: ¿dónde está la fuga de memoria aquí?

import time, string, pandas, numpy, gc 
class temp_class(): 

    def __init__(self, nrow = 1000000, ncol = 4, timetest = 5): 

     self.nrow = nrow 
     self.ncol = ncol 
     self.timetest = timetest 

    def createDataFrame(self): 

     print('Check memory before dataframe creating') 
     time.sleep(self.timetest) 
     self.df = pandas.DataFrame(numpy.random.randn(self.nrow, self.ncol), 
      index = numpy.random.randn(self.nrow), columns = list(string.letters[0:self.ncol])) 
     print('Check memory after dataFrame creating') 
     time.sleep(self.timetest) 

    def changeSize(self, from_ = 0, to_ = 100): 

     df_new = self.df[from_:to_].copy() 
     print('Check memory after changing size') 
     time.sleep(self.timetest) 

     print('Check memory after deleting initial pandas object') 
     del self.df 
     time.sleep(self.timetest) 

     print('Check memory after deleting copy of reduced pandas object') 
     del df_new 
     gc.collect() 
     time.sleep(self.timetest) 

if __name__== '__main__': 

    a = temp_class() 
    a.createDataFrame() 
    a.changeSize() 
  • Antes de la creación de trama de datos que tengo aprox. 15 MB de uso de la memoria

  • Después de crear - 67MB

  • Después de cambiar el tamaño de - 67 mb

  • Después de la eliminación de trama de datos original - 35MB

  • Después de eliminar reducida mesa - 31 mb.

16 mb?

Uso python 2.7.2 (x32) en la máquina con Windows 7 (x64), pandas. versión es 0.7.3. numpy versión 1.6.1 es

+0

Así es como funciona la asignación de memoria de Python. Probablemente no haya pérdida de memoria. – jozzas

Respuesta

26

Un par de cosas para señalar:

  1. En "Comprobación de la memoria después de cambiar el tamaño", no se haya eliminado la trama de datos original, sin embargo, por lo que este va a utilizar estrictamente más memoria

  2. El intérprete de Python es un poco codicioso sobre la celebración de la memoria del sistema operativo.

Analicé esto y puedo asegurarles que los pandas no están perdiendo memoria. Estoy usando el memory_profiler (http://pypi.python.org/pypi/memory_profiler) paquete:

import time, string, pandas, numpy, gc 
from memory_profiler import LineProfiler, show_results 
import memory_profiler as mprof 

prof = LineProfiler() 

@prof 
def test(nrow=1000000, ncol = 4, timetest = 5): 
    from_ = nrow // 10 
    to_ = 9 * nrow // 10 
    df = pandas.DataFrame(numpy.random.randn(nrow, ncol), 
          index = numpy.random.randn(nrow), 
          columns = list(string.letters[0:ncol])) 
    df_new = df[from_:to_].copy() 
    del df 
    del df_new 
    gc.collect() 

test() 
# for _ in xrange(10): 
#  print mprof.memory_usage() 

show_results(prof) 

Y aquí está la salida

10:15 ~/tmp $ python profmem.py 
Line # Mem usage Increment Line Contents 
============================================== 
    7       @prof 
    8  28.77 MB 0.00 MB def test(nrow=1000000, ncol = 4, timetest = 5): 
    9  28.77 MB 0.00 MB  from_ = nrow // 10 
    10  28.77 MB 0.00 MB  to_ = 9 * nrow // 10 
    11  59.19 MB 30.42 MB  df = pandas.DataFrame(numpy.random.randn(nrow, ncol), 
    12  66.77 MB 7.58 MB        index = numpy.random.randn(nrow), 
    13  90.46 MB 23.70 MB        columns = list(string.letters[0:ncol])) 
    14 114.96 MB 24.49 MB  df_new = df[from_:to_].copy() 
    15 114.96 MB 0.00 MB  del df 
    16  90.54 MB -24.42 MB  del df_new 
    17  52.39 MB -38.15 MB  gc.collect() 

Así que de hecho, hay más memoria en uso que cuando comenzamos ¿Pero está goteando?

for _ in xrange(20): 
    test() 
    print mprof.memory_usage() 

y de salida:

10:19 ~/tmp $ python profmem.py 
[52.3984375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59765625] 
[122.59765625] 
[122.59765625] 

Así que en realidad lo que se ha ido es en que el proceso de Python está aferrando a una piscina de la memoria teniendo en cuenta lo que ha estado usando para no tener que seguir pidiendo más memoria (y luego liberándolo) del sistema operativo host. No conozco todos los detalles técnicos detrás de esto, pero eso es al menos lo que está sucediendo.