2012-05-15 36 views
11

Tôi gặp sự cố rò rỉ bộ nhớ bằng cách sử dụng pandas thư viện ở python. Tôi tạo các đối tượng pandas.dataframe trong lớp của mình và tôi có phương thức, thay đổi kích thước khung dữ liệu theo các điều kiện của tôi. Sau khi thay đổi kích thước dataframe và tạo đối tượng gấu trúc mới, tôi viết lại pandas.dataframe gốc trong lớp của mình. Nhưng sử dụng bộ nhớ rất cao ngay cả sau khi giảm đáng kể bảng ban đầu. Một số mã ví dụ ngắn (tôi đã không viết quá trình quản lý, xem task manager):Pandas: bộ nhớ bị rò rỉ ở đâu?

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() 
  • Trước dataframe tạo Tôi có xấp xỉ. 15 mb sử dụng bộ nhớ

  • Sau khi tạo - 67MB

  • Sau khi thay đổi kích thước - 67 mb

  • Sau khi xóa dataframe gốc - 35MB

  • Sau khi xóa giảm bảng - 31 mb.

16 mb?

Tôi sử dụng trăn 2.7.2 (x32) trên máy tính Windows 7 (x64), gấu trúc. phiên bản là 0.7.3. numpy. phiên bản là 1.6.1

+0

Đây là cách phân bổ bộ nhớ của Python hoạt động. Có lẽ không có rò rỉ bộ nhớ. – jozzas

Trả lời

26

Một vài điều cần chỉ ra:

  1. Trong "Kiểm tra bộ nhớ sau khi thay đổi kích thước", bạn không xóa DataFrame gốc nào, vì vậy đây sẽ được sử dụng đúng bộ nhớ nhiều hơn

  2. Trình thông dịch Python hơi tham lam về việc giữ bộ nhớ hệ điều hành.

Tôi đã xem xét điều này và có thể đảm bảo với bạn rằng gấu trúc không bị rò rỉ bộ nhớ. Tôi đang sử dụng memory_profiler (http://pypi.python.org/pypi/memory_profiler) gói:

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) 

Và đây là kết quả

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

Vì vậy, trên thực tế, có nhiều bộ nhớ hơn trong sử dụng hơn khi chúng tôi bắt đầu. Nhưng nó có bị rò rỉ không?

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

Và đầu ra:

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] 

Vì vậy, trên thực tế những gì đang đi trên là quá trình Python được tổ chức vào một vũng bộ nhớ cho những gì nó được sử dụng để tránh phải giữ yêu cầu nhiều bộ nhớ hơn (và sau đó giải phóng nó) từ hệ điều hành máy chủ. Tôi không biết tất cả các chi tiết kỹ thuật đằng sau điều này, nhưng đó là ít nhất những gì đang xảy ra.