python列表对象内存未被释放

时间:2014-02-25 12:12:31

标签: python list memory

您好我的python程序会占用大量内存。

我简化了我的代码,这里是主要的功能

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

问题是我的观点 - 云数据集很大,大约100万点。我处理它并将其转换为高程图,所以我不再需要这些点...... 但是分配给这些点的内存仍然存在。我也尝试过del点。正如你在内存分析器中看到的那样,del只能释放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时的profiler输出

    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)

2 个答案:

答案 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?

答案 1 :(得分:0)

如果不再引用对象,则会删除对象。

此内存在内部进程释放,如果请求大小相同,可以在以后再次使用。只有满足某些条件,才会再次将内存返回给操作系统。

如果它是一个更大的对象,则可能是内存管理决定直接从OS调用mmap(),从而专门为此对象获取内存。释放后,内存立即可用。

如果你执行del points[:],只释放内容,我不确定是否收缩了对前一内容的引用的数组;做del points应该是更好的选择。

此外,Point()内部可能会保留对创建对象的引用(但我不知道为什么它应该这样做)。在这种情况下,del points不会释放它们,因为它们仍在内部引用。