游戏卡顿白皮书 › 按症状查找
一卡一卡:60 个原因及负责方
又称:卡顿、不流畅、像掉帧
在含图示的完整版症状词典中打开 →
动作不流畅,反复短暂停住又继续动。
其他角色或整个画面“顿一下、顿一下”。轨迹点时而挤在一起,时而拉开。
ping 值正常,多半是自己电脑的帧问题(客户端、操作系统);ping 忽高忽低,多半是 Wi-Fi 或线路的抖动。不过游戏内显示的 ping 通常是在每帧运行的游戏循环里测的,帧耗时一跳,ping 数字也可能跟着跳。
导致此症状的原因
L1 客户端游戏进程
- 帧耗时尖峰: 某一帧的计算比平时多花了几倍时间,画面短暂停顿。 (研发团队·客户端开发)
- 客户端垃圾回收: 回收用完丢弃的内存(垃圾对象)期间,整个游戏会停住。特点是按固定间隔一卡一卡。 (研发团队·客户端开发)
- 主线程同步加载/Shader 编译: 第一次绘制没见过的区域、怪物、特效之前,要先读文件、生成 Shader,画面因此卡住。 (研发团队·客户端开发)
- 存储设备过慢导致资源流式加载滞后: 在 HDD 这类慢速存储设备上,开放世界读取纹理、模型的速度跟不上移动,实体会晚出现,游戏也会因等待读取而一卡一卡。 (研发团队·客户端开发)
- 大规模同屏渲染负载: 攻城战、世界 BOSS 这类数百人同屏的场景,光是绘制开销就承受不住。 (研发团队·客户端开发)
- 没有插值缓冲或缓冲过短: 收到服务器数据包就立刻绘制,抖动(到达间隔的波动)会原样暴露在画面上。 (研发团队·客户端开发)
- 过度外推(航位推测): 数据包没到的这段时间,按最后的速度继续显示移动,发现猜错后再纠正回去。 (研发团队·客户端开发)
- 固定时间步长追赶失控: 停顿一次之后集中补算积压的计算,又因为这些计算再次积压。 (研发团队·客户端开发)
- 时钟同步误差: 客户端估算的服务器时间不准时,插值时间点和冷却判定都会错位。 (研发团队·客户端开发)
- float 时间精度丢失: 用精度较低的小数类型(float)保存游戏时间时,运行越久,时间分辨率(能区分的最小时间差)越低,动作和特效会发生颤动。 (研发团队·客户端开发)
- 垂直同步(V-Sync)与渲染队列: GPU 画好的帧先在队列里攒几张,再按显示器刷新周期送出,这段时间里输入响应就会变迟。 (研发团队·客户端开发)
- 客户端内存泄漏: 运行越久内存占用越大,游戏越来越慢,最终被强制关闭。 (研发团队·客户端开发)
- 游戏安全模块(反作弊)扫描: 为防外挂,与游戏一起运行的安全模块会定期扫描。扫描太重,或与安全服务器之间的心跳(定期发送的存活确认信号)延迟,就会一卡一卡或掉线。 (研发团队·客户端开发)
L2 客户端操作系统与设备
- 后台进程占用 CPU: 杀毒扫描、Windows 更新、直播软件、浏览器视频占着 CPU 核心时,游戏线程分不到 CPU,只能等待。 (外部·外部)
- 省电模式/发热降频: 笔记本电池模式、手机省电模式、设备发热都会让 CPU、GPU 降速。发热的特点是一开始正常,过一阵子才变慢。 (外部·外部)
- 定时器精度: Windows 默认定时器以 15.6 ms 为单位,“只休眠 1 ms”实际要等到下一个定时器周期,最长会拉长到 15.6 ms。 (研发团队·客户端开发)
- 安全软件检查数据包: 杀毒软件、防火墙逐个检查数据包会增加延迟,检查过度时还会把游戏误判为攻击并拦截。 (外部·外部)
- 客户端内存不足/swap: 同时开着几十个浏览器标签页和游戏时,操作系统会把游戏的一部分内存换出到磁盘。 (外部·外部)
- 显存(VRAM)不足: 画质选项要求的内存超过显卡显存时,操作系统要把纹理换到系统内存再取回,画面就会一卡一卡。 (研发团队·客户端开发)
- Wi-Fi 后台扫描: 操作系统为了搜索周围的 Wi-Fi,会定期切换信道,这期间通信会短暂停顿。 (外部·外部)
- 网卡省电/驱动问题: 有线网卡、Wi-Fi 芯片在数据包之间进入省电状态时,重新唤醒需要时间。 (外部·外部)
- 窗口最小化/失去焦点时处理受限: 切到别的窗口或最小化游戏时,游戏和 Windows 为了省电会让游戏降速运行。切回来时,积压的数据包会一下子涌来,或者已经掉线。 (研发团队·客户端开发)
- 游戏内覆盖层干扰: 聊天软件、启动器、录屏软件、FPS 显示工具为了在游戏画面上叠加绘制自己的 UI,会介入游戏的渲染过程(hook)。每帧的工作量随之增加,偶尔还会与游戏冲突,导致顿一下或游戏被强制关闭。 (外部·外部)
L3 家庭网络
L4 公网链路
- 卫星互联网(低轨、静止轨道): 卫星互联网的信号要在太空中往返。静止轨道卫星光是往返就超过 0.5 秒;Starlink 这类低轨卫星平时很快,但在重新分配路径的瞬间延迟会波动,还可能短暂中断。 (外部·外部)
- 高峰时段对等互联链路拥塞: 晚上 9~11 点前后视频流量激增,运营商之间的互联链路(对等互联)容易拥塞。 (运维团队·网络运维)
- ECMP 单条路径故障: 运营商和数据中心通往同一目的地的路径往往有多条,每个连接固定走其中一条。只要有一条路径出故障,分到这条路径上的人就会一直卡。 (运维团队·网络运维)
L6 服务器网卡
- 虚拟化开销/邻居干扰: 同一台物理服务器上的其他虚拟机大量占用网络和 CPU 时,自己这台服务器的处理会不规律地被拖后。 (运维团队·系统运维)
L7 服务器操作系统(内核)
- 线程过多与上下文切换: 线程数远多于核心数时,操作系统光是让它们轮流运行就要耗掉大量 CPU。 (研发团队·服务器开发)
- CPU 窃取时间(虚拟机): 物理服务器(hypervisor)把虚拟机的 CPU 时间暂时让给其他虚拟机期间(CPU 窃取),游戏服务器会停住。 (运维团队·系统运维)
- 容器 CPU 限流(CFS 配额): 给容器设置 CPU 上限后,一旦在规定周期(通常为 100 ms)内用完配额,周期剩下的时间里就会被强制停住(限流)。 (运维团队·系统运维)
- 内存回收/规整导致的停顿: 操作系统为了凑出大页(huge page)而做内存规整,或为补充空闲内存而回收内存时,进程会停住。 (运维团队·系统运维)
- 定时任务: 每天在同一时刻运行的日志压缩、备份、安全扫描会占用 CPU 和磁盘。 (运维团队·系统运维)
- OS/内核/驱动/固件更新后的性能变化: 游戏代码没变,服务器的 OS、内核、驱动、固件更新之后却开始变慢。更新可能会改变默认值、调度器、CPU 漏洞缓解措施(mitigations)和驱动行为。 (运维团队·系统运维)
L9 服务器游戏进程
- Tick 超出预算: 一个 tick 内要做的事超出预算时,服务器的 tick 周期会被拉长,整个区域都会变慢或一卡一卡。 (研发团队·服务器开发)
- 视野(AOI)计算激增(N²): 所有人两两比较谁能看到谁,人数变成 10 倍时,计算量就会变成 100 倍。 (研发团队·服务器开发)
- 游戏线程中的同步调用: tick 中途等待 DB 响应或文件写入时,等多久,服务器上整个游戏的运行就停多久。 (研发团队·服务器开发)
- 定时器集中触发: 所有怪物刷新、所有 buff 到期、整点奖励都挤在同一个 tick 时,那个 tick 的负载就会高出几十倍。 (研发团队·服务器开发)
- 实体堆积(未清理的物品/召唤物): 本该消失的地面物品、召唤物、已结束的定时器没有被清理而不断堆积,服务器开得越久,每个 tick 要做的事就越多。 (研发团队·服务器开发)
L10 内存
- 脚本引擎 GC 停顿: 即使是 C++ 服务器,如果任务、AI、技能用 Lua 等脚本来跑,脚本引擎执行 GC 期间,对应的场景也会停住。 (研发团队·服务器开发)
- 内存分配暴增: 活动期间大量创建临时对象,GC 会比平时频繁得多。 (研发团队·服务器开发)
L11 磁盘
- 同步写日志: 游戏线程每写一行日志都要等磁盘完成,磁盘一忙,游戏逻辑也跟着停住。 (研发团队·服务器开发)
- fsync 风暴: 要求把数据“真正”写进磁盘(确保落盘)时,视磁盘不同每次要花 0.1 ms 到几十 ms;请求一集中,队列就会变长。 (研发团队·服务器开发)
- 云盘突发积分耗尽: 部分云盘和小规格实例有突发积分,可以短时间超过基准性能运行。繁忙时段一长、积分耗尽,速度就会突然下降。 (运维团队·系统运维)
- 备份/压缩/扫描任务: 凌晨的备份、日志压缩、安全扫描独占磁盘时,游戏服务器的读写会被挤到后面。 (运维团队·系统运维)
L12 数据库
- 检查点/日志刷盘: DB 定期把内存中的变更集中写入磁盘,那一刻查询会变慢。 (运维团队·数据库运维)
L13 服务器架构与运维
- 日志/监控过载: 出故障时日志会激增,同步发送日志的服务器会被日志拖得更慢。 (研发团队·服务器开发)
同步设计
- 帧同步中等待最慢的玩家: 所有人一起计算同一个逻辑帧的结构下,只要有一个人的输入晚到,所有人都得等。 (研发团队·服务器开发)
- 没有时间戳、一到就播放: 服务器事件不附带发生时刻、一收到就播放时,网络抖动会原封不动地让表现时机忽快忽慢。 (研发团队·客户端开发)
- 主机(房主)结构: 由某个玩家的电脑充当服务器时,这个人的线路和电脑性能决定了所有人的体验。 (研发团队·服务器开发)
- 快照发送频率低: 服务器每秒只发几次位置更新(快照)时,插值缓冲就得相应拉长,看到的其他角色也就是更久以前的状态。 (研发团队·服务器开发)
只有部分人遇到的问题
- 每个玩家的输入缓冲大小: 服务器为每个人先攒一点输入,每个 tick 取出一个使用时,别人看起来很流畅,但本人动作在服务器上确定的时间也会相应推迟。 (研发团队·服务器开发)
- 怪物控制权在慢的客户端上: 有的游戏为减轻服务器负载,把怪物的移动计算交给附近某个玩家的客户端。这个人的线路差时,这只怪物在所有人的画面上都会动得很怪。 (研发团队·服务器开发)
- 内存/显存不足导致流式加载失败: 两个客户端共用显存时,新需要的模型、纹理没有地方加载,有一部分就画不出来。 (研发团队·客户端开发)
- 时钟估算误差导致实体被搁置: 客户端估算的服务器时间不准时,刚到达的实体信息会被当成“还在未来”而搁置,或被当成“太旧”而丢弃。 (研发团队·客户端开发)
TCP 重传的根本原因
- 乱序导致的虚假快速重传: 数据包经过多条路径或聚合链路时顺序被打乱,接收方会用重复 ACK 通知“有包缺失”,发送方就把好好的包又发一遍。 (运维团队·网络运维)
查看含图示的完整版症状词典