城市模拟“卡”不是一个症状,而是至少三个:镜头掉帧、时间走不动、点了没反应。它们的瓶颈不同,修法也不同。大发娱乐App里的大型城市尤其如此,先分清再动手,能省下大半试错时间。
先分清三种“卡”,排查方向完全不同
第一种是画面卡:拖动镜头掉帧,暂停以后依旧如此。这主要是渲染和显示的问题,跟居民有多少关系不大。第二种是时间推进卡:游戏里的一天原本几秒走完,现在要十几秒,居民行动、交通、消费的结算跟不上。第三种是操作响应卡:点一下建筑,面板要等一会儿才弹出来,通常是界面线程被别的计算占住了。
大发娱乐App里的城市模拟,是把居民决策、交通流和经济结算放在同一条时间线上推进的。所以“时间推进变慢”才是模拟负载的真信号,而单纯的画面掉帧,更多和设备图形能力、屏幕分辨率有关。排查的第一步不是去改设置,而是弄清自己遇到的是哪一种。
有一个几乎不花时间的测试:先把模拟暂停,再拖动镜头。暂停后镜头依然卡,问题在渲染一侧;暂停后镜头流畅、一恢复运行就卡,问题在模拟一侧。后面的内容只讨论第二种情况,也就是模拟本身跑不动。
用一个模拟示例把负载拆开:卡在哪一层
下面用一座假设的城市来说明逻辑。假设场景:4000个居民Agent、300家企业、一张有1200个路段的路网。这些数字是模拟示例,不是任何实测配置,只用来展示各个子系统各自随什么增长。
| 子系统 | 负载随什么增长 | 主要吃什么 | 变慢时的表现 |
|---|---|---|---|
| 居民决策 | 居民数量 × 每天需要重新决策的次数 | CPU | 每到“上班前”“下班后”这类集中时段,推进明显变慢 |
| 路径与交通 | 同时在途的人数 × 路段数 | CPU | 早晚高峰变慢,深夜恢复 |
| 经济结算 | 企业数 × 商品种类 × 结算频率 | CPU,少量内存 | 每周末、每月末卡一下,之后恢复 |
| 记忆与历史 | 居民数量 × 已运行的游戏天数 | 内存 | 运行越久越慢,重启后又好了 |
| 渲染 | 屏幕上可见的对象数 | GPU | 拖动镜头掉帧,暂停后仍然卡 |
这张表最有用的是最后一列。“什么时候卡”比“卡到什么程度”更能说明问题:卡在固定的时间点,多半是周期性结算或集中决策;越玩越卡、重启就好,是内存里积累了东西;只在镜头动的时候卡,是渲染。
CPU 瓶颈长什么样:卡得有规律,而且跟规模成正比
居民决策是CPU开销的大头。城市模拟为什么需要批量推理而不是让居民一个个慢慢想,原因就在这里:几千个居民如果逐个走一遍完整的决策流程,一个游戏小时的耗时会随人数线性上升;批量处理把相似的居民合并成一批统一计算,才能把单位时间的开销压下来。即便如此,居民越多,一批的体量越大,总耗时仍会增长。
判断是不是CPU瓶颈,可以看三个特征。其一,把模拟速度调到最慢,单日耗时明显恢复,说明系统本身没坏,是吞吐不够。其二,卡顿发生的时点和游戏内的作息节奏吻合,比如集中出门、集中下班。其三,设备明显发热,随后整体变慢,这多半是系统为了控温主动降低了处理器频率,此时换个凉快的环境、退掉后台应用,往往比调游戏设置更管用。
这里有一个常见误会:CPU占用率显示不高,就以为不是CPU的问题。模拟计算常常集中在少数几个线程上,整体占用率看着很低,某一个核心其实已经打满。所以看到“占用不高但依然卡”,不要急着排除。
内存瓶颈长什么样:越玩越卡,重启又好了
内存的症状和CPU很不一样,它跟“规模 × 时间”有关。居民的记忆、习惯、价格参照点、历史曲线会随着游戏日累积,运行三百天的城市比刚开局的城市占用多得多。可用内存被吃紧以后,系统开始频繁换页或者回收后台,表现为操作延迟、切出去再回来要重新加载,严重时直接退出。
为什么模拟游戏对内存这么敏感,需要单独讲一讲,可以看Agent状态和世界数据到底保存了什么那篇。这里只需要记住排查上的含义:如果一座城市“前十天很顺、第两百天开始卡”,先怀疑内存,而不是先怀疑设备老了。验证办法很简单,保存后完全退出再进入同一个存档,如果一开始流畅、又慢慢变卡,基本就是累积型问题。
一套十分钟内做得完的排查顺序
按下面的顺序来,每一步都是在排除一类原因,做完一步再做下一步,不要同时改好几处,否则不知道哪一步起了作用。
- 暂停模拟,拖动镜头。仍然卡,去看画面与分辨率一侧;不卡,继续往下。
- 把模拟速度调到最低,观察单日耗时。恢复正常说明是吞吐不足,用降速或降规模解决;仍很慢说明有别的东西占着资源。
- 打开系统自带的性能或电池页面,看内存占用、是否发热降频、后台有没有别的大户。手机上还要看剩余存储空间,空间过紧同样会拖慢读写。
- 保存并完全退出,重新进入同一存档。刚进入流畅、过一阵变卡,指向内存累积;一进入就卡,指向规模或设备算力。
- 如果App提供居民详细程度、可视范围或模拟规模一类的选项,只调一项,再重复第二步。
- 仍无法定位,再联系官方帮助渠道。带上设备型号、系统版本、城市大致规模、已运行的游戏天数,以及卡顿发生的时间点,比只说“很卡”有用得多。
不同版本里这些选项的名称和位置可能不一样,以App内实际页面为准。
降规模不等于降质量:哪些可以降频,哪些不能碰
需要降负载时,系统设计上有可以放松的部分,也有不能动的部分。可以放松的是“精度”,比如不在视野内、跟玩家当前决策关系不大的居民,可以降低重新决策的频率,合并成更粗的批次;交通里一些远离玩家关注区域的路段,可以用更粗的流量估算。
不能动的是“守恒”。经济结算里,钱、库存和商品的进出必须对得上,偷工减料会让账目慢慢漂移,一百周以后整个市场表现出很奇怪的形状。关键居民的记忆和习惯也不宜随意清掉:居民忘了自己被堵过、被涨过价,后面的路线选择和消费选择就会重新回到“初始状态”,模拟就退化成了随机游走。
所以大发娱乐的设计思路是,允许玩家用规模和速度换流畅度,而不是靠删掉系统内部的因果关系来换。在设置里把居民规模降一档,几乎总比想办法关闭某个子系统更安全。
用前面的模拟示例来说,把4000个居民降到3000个,居民决策这一项的耗时大致会按比例下降,而经济结算的账目依然完整,因为企业和商品没有减少。相反,如果为了省时间把部分企业的库存结算跳过,短期内确实快了,可几十个游戏日之后,价格与库存的对应关系就会失真,那时再排查,已经分不清是设备问题还是数据漂移。这个例子的数字仍是假设,用意是说明:能降的是“同时处理多少”,不能降的是“账有没有算对”。
大发娱乐经营AI和城市AI共用同一套结算与调度思路,因此在经营类世界里,这条原则同样适用:可以减少同时被重新评估的对象,却不应该让任何一笔交易“凭空消失”。
有些卡是模拟自己的行为,不是设备出了问题
还要提醒一类情况:堵车高峰、月末结算、一场大事件刚触发,这几种时刻计算量确实集中,短暂的变慢是正常的,几秒后恢复就不必处理。判断标准是“会不会自己恢复”。能恢复的,是峰值;恢复不了的,才是需要排查的瓶颈。
另外,同一台设备上不同类型的世界负载差别很大:一座只有几百居民的小城,和一个包含上千居民、上百家企业的大城,对设备的要求不在同一个量级。很多“卡”其实是规模选大了,而不是设备坏了。如果想理解Agent数量、模拟速度和设备性能之间的关系,可以从这个角度去看:先定要跑多大的城市,再决定设备够不够。
刚完成大发娱乐下载的新设备,最好先用一座中等规模的大发娱乐城市AI世界试跑几天,记下单日耗时,再逐步加大规模。这样得到的是自己设备的基线,之后任何一次变卡,都能对着基线判断是规模变了还是设备状态变了。
一个务实的判断是:如果降低一档规模就能流畅,那这台设备适合的是中等规模的城市,重装和反复清理数据并不会让它多承载一千个居民。