Панды: где здесь утечка памяти?

Я сталкиваюсь с проблемой утечек памяти, используяpandas библиотека вpython, я создаюpandas.dataframe объекты в моем классе и у меня есть метод, который изменяет размер информационного кадра в соответствии с моими условиями. После изменения размера фрейма данных и создания нового объекта pandas я переписываю оригинальный класс pandas.dataframe в своем классе. Но использование памяти очень велико даже после значительного сокращения исходной таблицы. Некоторый код для краткого примера (я не писал менеджер процессов, см. Диспетчер задач):

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()

Before dataframe creating I have approx. 15 mb of memory usage

After creating - 67mb

After changing size - 67 mb

After deleting original dataframe - 35mb

After deleting reduced table - 31 mb.

16 mb?

Я использую Python 2.7.2 (x32) на машине Windows 7 (x64), панды.version составляет 0,7,3. NumPy.version это 1.6.1

 jozzas16 янв. 2013 г., 05:28
Вот как работает распределение памяти в Python. Вероятно, нет утечки памяти.

Ответы на вопрос(1)

In "Check memory after changing size", you haven't deleted the original DataFrame yet, so this will be using strictly more memory

The Python interpreter is a bit greedy about holding onto OS memory.

Я изучил это и могу заверить вас, что у панд нет утечки памяти. Я использую пакет memory_profiler (http://pypi.python.org/pypi/memory_profiler):

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)

А вот и вывод

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()

Так что, действительно, используется больше памяти, чем когда мы начинали. Но это протекает?

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

И вывод:

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]

Таким образом, на самом деле то, что произошло, заключается в том, что процесс Python удерживает пул памяти, учитывая то, что он использует, чтобы избежать необходимости запрашивать больше памяти (и затем освобождать ее) из хост-ОС. Я не знаю всех технических деталей, стоящих за этим, но это, по крайней мере, то, что происходит.

Ваш ответ на вопрос