链接列表的内存优化

时间:2014-06-26 22:31:39

标签: python python-3.x out-of-memory

我最近创建了一个脚本,使用从几个迷宫节点构建的自定义迷宫类生成随机迷宫。每个节点如下所示:

class mazeNode:
    def __init__(self, pos, conn = None):
        self.pos = pos
        if conn:
            self.conns = [conn]
        else:
            self.conns = []

conn是另一个mazeNode对象,并且在创建迷宫期间更改self.conns以包括该节点连接到的每个mazeNode对象。 pos是具有节点位置的元组。在创建迷宫时,根据深度优先搜索算法创建mazeNode对象,并在分支中链接在一起。

脚本效果很好,可以在大约10秒内创建一个大小为500 * 500的迷宫。但是,它似乎没有非常高效的内存。我设法创建了一个大小为6000 * 6000的迷宫,但是当我尝试10000 * 10000时,无论我做什么,我都会收到内存错误,即使我分配了50GB的虚拟内存。对于那个大小,我最终得到10 ^ 8个mazeNode对象。

我尝试使用shelve模块,但这会使脚本运行速度变慢而无法使用,对于更大的迷宫,我收到了一个递归深度错误(由于不必要的递归,脚本可能很慢)。

我想知道是否有任何方法可以优化脚本的内存使用量,同时保持速度。所有节点都链接在一起,但它们并不一定都在RAM中。

EDIT 迷宫课程如下:

class Maze:

    def __init__(self, xSize, ySize):

        self.pos = (xSize//2, ySize//2)
        self.xSize = xSize
        self.ySize = ySize
        self.directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        self.visit = set([self.pos])
        self.maze = mazeNode(self.pos)
        self.node = self.maze
        self.stack = Stack()
        self.deadEnds = 0
        for i in randPerm(list(range(4))):
            self.stack.put(mazeNode(add(self.pos, self.directions[i]), self.node))

    def makeMaze(self):
        while True:
            while self.node.pos in self.visit and not self.stack.isEmpty():
                self.node = self.stack.pop()
            if self.stack.isEmpty():
                break
            if self.node.pos not in self.visit:
                self.visit.add(self.node.pos)

            for conn in self.node.conns:
                conn.conns.append(self.node)

            tempCount = 0
            for i in randPerm(list(range(4))):
                pos = add(self.node.pos, self.directions[i])
                if pos not in self.visit and check(pos, self.xSize, self.ySize):
                    self.stack.put(mazeNode(pos, self.node))
                    tempCount += 1
            if tempCount == 0:
                self.deadEnds += 1
        if len(self.maze.conns) == 1:
            self.deadEnds += 1

编辑2:

我使用了广告位:并按如下方式编辑了mazeNode类:

class mazeNode:
    __slots__ = ('posx', 'posy', 'conns', )

    def __init__(self, pos, conn = None):
        self.posx = pos[0]
        self.posy = pos[1]
        self.conns = [conn] if conn else []

并使用sys.getsizeof()来获取类实例的大小。

print(sys.getsizeof(self.maze), sys.getsizeof(self.maze.posx), sys.getsizeof(self.maze.posy), sys.getsizeof(self.maze.conns))

打印64 28 28 96。但是,如果我删除__slots__,我会56 28 28 96,这看起来很奇怪。我该怎么解释这个? __slots__无效吗?

1 个答案:

答案 0 :(得分:0)

__slots__使用非常简单,只需将它们添加到类定义中即可:

class MazeNode(object):
    __slots__ = ('pos', 'conn', )

    def __init__(self, pos, conn=None):
        self.pos = pos
        self.conns = [conn] if conn else []

唯一需要记住的是,插槽类型/类不能动态添加属性。只能设置和/或修改__slots__中列出的属性。即使他们会显着降低每个对象的内存使用量,也不要为你定义的每个类定义插槽。明智地使用它们。