含Resource对象的resourceList调用get_dispChar耗时过高问题排查
问题分析与修复方案
嘿,这个问题我之前在做类似的 tile-based 游戏时也碰到过,咱们来一步步拆解可能的原因,再给出对应的修复思路!
可能的核心原因
从你描述的现象(仅当resourceList有元素时get_dispChar耗时飙升)来看,大概率是这个函数在处理资源列表时存在低效的重复计算或遍历逻辑,常见的情况有这几种:
- 无缓存的全量遍历:每次调用
get_dispChar都完整遍历resourceList,比如找优先级最高的资源、拼接所有资源字符,当列表有元素后,遍历+循环内操作的开销就会凸显出来。 - 冗余的属性访问/计算:在循环里反复访问
Resource的动态属性,或者每次都重新计算同一个值(比如资源对应的显示字符、优先级权重),没有提前缓存结果。 - 低效的字符串操作:如果函数里用
+拼接多个资源的显示字符(Python字符串是不可变的,每次+都会生成新对象),当资源数量增加时,这种操作的耗时会指数级上升。 - 不合适的数据结构:用普通列表存储资源,每次查找、排序都要做全量操作,没有用字典、有序列表这类更高效的结构。
针对性修复方案
1. 缓存计算结果,避免重复执行
给TerrainTile添加缓存属性,只有当资源列表或影响显示的属性变化时,才重新计算显示字符:
class TerrainTile: def __init__(self): self.tileX = 0 #world x coord self.tileY = 0 #world y coord self.elevation = 0 #int from 0-100, tells how high the highest point on the tile is self.symbol = '?' self.fgCol = [0,0,0,0] self.bkCol = [0,0,0,0] self.resourceList = [] self._cached_disp_char = None # 缓存显示字符 self._highest_priority_res = None # 缓存最高优先级资源 # 封装资源的添加/移除操作,触发缓存失效 def add_resource(self, resource): self.resourceList.append(resource) # 更新最高优先级资源(假设Resource有priority属性) if not self._highest_priority_res or resource.priority > self._highest_priority_res.priority: self._highest_priority_res = resource self._cached_disp_char = None # 缓存失效 def remove_resource(self, resource): self.resourceList.remove(resource) # 移除后重新计算最高优先级资源 if self._highest_priority_res == resource: self._highest_priority_res = max(self.resourceList, key=lambda r: r.priority) if self.resourceList else None self._cached_disp_char = None # 缓存失效 def get_dispChar(self): if self._cached_disp_char is not None: return self._cached_disp_char # 无资源时返回默认符号 if not self.resourceList: self._cached_disp_char = self.symbol else: # 假设取最高优先级资源的显示字符(根据你的逻辑调整) self._cached_disp_char = self._highest_priority_res.disp_char return self._cached_disp_char
2. 优化遍历与计算逻辑
- 如果不需要处理所有资源,只需要特定条件的资源(比如优先级最高),就不要遍历整个列表,而是在资源变更时提前维护好目标资源。
- 把循环内的重复计算(比如资源字符的映射规则)提到循环外面,或者放到
Resource类的静态属性里,避免每次都重新计算。
3. 改进字符串操作
如果需要拼接多个资源的显示字符,用str.join()替代+,比如:
# 低效写法 disp_char = '' for res in self.resourceList: disp_char += res.disp_char # 高效写法 disp_char = ''.join([res.disp_char for res in self.resourceList])
4. 更换更高效的数据结构
- 如果需要频繁查找特定类型的资源,把
resourceList换成字典,键是资源类型,值是资源对象,这样查找时间复杂度从O(n)降到O(1)。 - 如果需要按优先级排序,在添加资源时就维护一个已排序的列表,而不是每次调用
get_dispChar时再排序。
内容的提问来源于stack exchange,提问作者J Cline
相关产品推荐
相关产品推荐

