python内存使用dict和变量大数据

2024-09-28 20:52:19 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,我正在用python3.4制作一个游戏。在游戏中我需要跟踪地图。这是一个连接的房间的地图,从(0,0)开始,在每个方向继续,以过滤的随机方式生成(只有下一个位置的正确匹配用于随机列表选择)。在

我有几种类型的房间,它们有一个名称和一系列门:

RoomType = namedtuple('Room','Type,EntranceLst')
typeA = RoomType("A",["Bottom"])
...

对于目前的地图,我记下了位置和房间类型:

^{pr2}$

我有一个生成900000个房间的循环,用来测试内存使用情况。 当我运行它时,我得到大约600和800Mb。 我想知道是否有一种方法可以优化它。在

我试着用而不是做

navMap = {currentRoomPos: currentRoomType}

我会的

navMap = {currentRoomPos: "A"}

但这并没有真正改变用法。在

现在我在想,我是否可以——也应该——列出所有类型的列表,并为每种类型保留发生这种情况的位置。不过,我不知道它是否会对python管理其变量的方式产生影响。在

这几乎是一个思想实验,但如果有任何有用的东西,我可能会实施它。在


Tags: 名称游戏类型列表type方式地图情况
1条回答
网友
1楼 · 发布于 2024-09-28 20:52:19

您可以使用sys.getsizeof(object)来获取Python对象的大小。但是,在对容器调用sys.getsizeof时必须小心:它只给出容器的大小,而不是内容有关如何获得容器的总大小(包括内容)的说明,请参见this方法。在这种情况下,我们不需要太深入:我们只需手动合计容器的大小及其内容的大小。在

相关类型的尺寸为:

# room type size
>>> sys.getsizeof(RoomType("A",["Bottom"])) + sys.getsizeof("A") + sys.getsizeof(["Bottom"]) + sys.getsizeof("Bottom")
233

# position size
>>> sys.getsizeof((0,0)) +  2*sys.getsizeof(0)
120

# One character size
>>> sys.getsizeof("A")
38

让我们看看不同的选项,假设您有N个房间:

  1. 来自position -> room_type的字典。这涉及到在内存中保留N*(size(position) + size(room_type)) = 353 N个字节。在
  2. 来自position -> 1-character string的字典。这涉及到在内存中保留N*158个字节。在
  3. 来自type -> set of positions的字典。这涉及到保留N*120字节以及存储字典键的微小开销。在

在内存使用方面,第三种选择显然更好。然而,与通常情况一样,您需要权衡CPU内存。值得简要考虑一下您可能要执行的查询的计算复杂性。要找到给定位置的房间类型,请执行以下三个选择:

  1. 在字典里查这个位置。这是一个O(1)查找,因此您将始终具有相同的运行时间(大约),与房间的数量无关(对于大量的房间)。在
  2. 相同
  3. 看看每一种类型,并询问每种类型的位置是否在该类型的位置集中。这是一个O(ntypes)查找,也就是说,它所花费的时间与您拥有的类型数量成正比。请注意,如果您使用list而不是set来存储给定类型的房间,那么这将增长到O(nrooms * ntypes),这将影响您的性能。在

与往常一样,在优化时,重要的是要考虑优化对内存使用和CPU时间的影响。两人经常意见不合。在

另一种选择是,如果您的映射足够矩形,那么可以考虑将类型保存在二维numpy字符数组中。我相信这样会更有效率。numpy数组中的每个字符都是一个字节,因此内存使用量将大大减少,而且CPU时间仍然是O(1)从房间位置到类型的查找:

^{pr2}$

一些额外的小规模优化:

将房间类型编码为int而不是字符串。int的大小为24字节,而一个字符串的大小为38。在

将位置编码为单个整数,而不是元组。例如:

# Random position
xpos = 5
ypos = 92

# Encode the position as a single int, using high-order bits for x and low-order bits for y
pos = 5*1000 + ypos

# Recover the x and y values of the position.     
xpos = pos / 1000
ypos = pos % 1000

请注意,这会降低可读性,因此只有当您想压缩性能的最后一部分时才值得这样做。实际上,您可能希望使用2的幂次而不是10的幂作为分隔符(但是10的幂有助于调试和可读性)。请注意,这会使每个位置的字节数从120到24。如果您真的这样做,请考虑使用__slots__定义一个Position类来告诉Python如何分配内存,并向类添加xpos和{}属性。您不希望在代码中使用pos / 1000pos % 1000语句。在

相关问题 更多 >