2014-02-25 57 views
0

您好我正在從我的python程序獲得海量內存使用。python列表對象內存不被釋放

我已經簡化了我的代碼,這裏是主要的功能

points = [] 
read_pcd(TEST1_PCD, points) 
del points[:] # i also tried del points 
# program exits here 

的問題是我的點雲數據集很大,約1萬點。我處理它並將其轉換爲高程圖,因此我不再需要這些點...但是分配給這些點的內存仍然存在。我也嘗試過刪除點。正如你可以在內存分析器中看到的那樣,刪除點只釋放7 Mb .... python是否不打算釋放列表元素佔用的內存?因爲我擔心我的項目後期內存不足。

這是內存分析器我以前https://pypi.python.org/pypi/memory_profiler

這裏是REFFERENCE的read_pcd功能

def read_pcd(fname, points): 
    data_start = False 
    with open(fname, 'r') as f: 
     for i, line in enumerate(f): 
      words = line.split() 
      if words[0] == "DATA": 
       data_start = True 
      elif data_start == True: 
       point = Point(float(words[0]), float(words[1]), float(words[2])) 
       points.append(point) 

    Line # Mem usage Increment Line Contents 
================================================ 
    17 23.559 MiB 0.000 MiB @profile 
    18        def main(): 
    19 24.121 MiB 0.562 MiB  rospy.init_node('traversability_analysis_node') 
    20 24.129 MiB 0.008 MiB  points = [] 
    21 1322.910 MiB 1298.781 MiB  read_pcd(TEST1_PCD, points) 
    22 1315.004 MiB -7.906 MiB  del points[:] 



class Point(object): 
def __init__(self, x=0.0, y=0.0, z=0.0, intensity=255, cart=True, range_m=0, az=0, elv=0): 
    # http://www.mathworks.com.au/help/matlab/ref/cart2sph.html 
    DEG2RAD = m.pi/180.0 
    if cart == True: 
     self.x = x 
     self.y = y 
     self.z = z 
     self.intensity = intensity 
     self.range = np.sqrt(x**2 + y**2 + z**2) 
     self.azimuth = np.arctan2(y, x) 
     r_xy = np.sqrt(x**2 + y**2) 
     self.elvation = np.arctan2(z, r_xy) 
    else: 
     elv = elv*DEG2RAD 
     az = az*DEG2RAD 
     self.x = range_m*np.cos(elv)*np.cos(az) 
     self.y = range_m*np.cos(elv)*np.sin(az) 
     self.z = range_m*np.sin(elv) 
     self.range = range_m 
     self.azimuth = az 
     self.elvation = elv 
     self.intensity = intensity 

探查輸出調用GC.Collect的時候

Line # Mem usage Increment Line Contents 
================================================ 
    18 23.555 MiB 0.000 MiB @profile 
    19        def main(): 
    20 24.117 MiB 0.562 MiB  rospy.init_node('traversability_analysis_node') 
    21 24.125 MiB 0.008 MiB  points = [] 
    22 1322.914 MiB 1298.789 MiB  read_pcd(TEST1_PCD, points) 
    23 1322.914 MiB 0.000 MiB  gc.collect() 
    24 1315.008 MiB -7.906 MiB  del points 
    25 1315.008 MiB 0.000 MiB  time.sleep(5) 
+0

爲什麼你做'del points [:]'而不是'del points'? – bgusach

+0

是的,我試了兩個相同的結果。 – SentinalBais

+0

你已經得到了下面的答案。現在你真的需要將所有數據加載到內存中嗎?如果沒有,將你的函數變成一個生成器並迭代它可以避免整個問題。 –

回答

1

不幸的是,你可能無法釋放所有的內存:

http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm

另外,儘量GC.Collect的(),並看到了第二個答案:

How can I explicitly free memory in Python?

+0

我猜的點對象是像文章說的太大......這是否意味着永遠不會在應用程序的生命週期中釋放點?或者是考慮爲python解釋器釋放的內存,雖然它從操作系統的角度來看看佔用了... – SentinalBais

0

刪除對象發生,如果它不再被引用。

該內存被釋放過程在內部和如果存在用於大約相同的尺寸的請求可以在以後再次使用。只有滿足某些條件時,內存纔會再次返回到操作系統。

如果它是一個更大的物體,它可能是內存管理的決定,而不是直接調用從OS mmap(),從而獲取內存專門爲這個對象。釋放它後,內存立即可用。

如果你這樣做del points[:],只有內容中解脫出來,我不知道,如果列保持前者內容的引用是收縮;做del points應該是更好的選擇。

此外,它可能是Point()內部保存到創建的對象(我不知道爲什麼它應該這樣做,但是)的參考。在這種情況下,del points將不會釋放它們,因爲它們仍在內部引用。

+0

我試過刪除點,它與del點[:]有相同的效果。 – SentinalBais

+0

import gc; gc.collect() – IceArdor

+0

我嘗試了gc.collect方法,並在它後面添加了睡眠。它仍然沒有工作,不知道如果它是分析器.... – SentinalBais