

子玥酱 (掘金 / 知乎 / CSDN / 简书 同名)
大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向: 前端 / 跨端 / 小程序 / 移动端工程化 内容平台: 掘金、知乎、CSDN、简书 创作特点: 实战导向、源码拆解、少空谈多落地 **文章状态:**长期稳定更新,大量原创输出
我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在"API 怎么用",而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源 (工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学"明白",也用"到位"
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
-
- 引言
- 一、先理解一帧是怎么出来的
-
- [Game Thread](#Game Thread)
- RenderThread
- GPU
- [二、为什么 RenderThread 会成为瓶颈?](#二、为什么 RenderThread 会成为瓶颈?)
- [三、RenderThread 每帧都在做什么?](#三、RenderThread 每帧都在做什么?)
-
- [1、Visible Culling](#1、Visible Culling)
- [2、Render Queue 排序](#2、Render Queue 排序)
- 3、Batch
- [4、Command Buffer](#4、Command Buffer)
- [四、为什么 DrawCall 太多会卡 RenderThread?](#四、为什么 DrawCall 太多会卡 RenderThread?)
- [五、UI 为什么特别容易卡 RenderThread?](#五、UI 为什么特别容易卡 RenderThread?)
- [六、Particle 为什么容易炸?](#六、Particle 为什么容易炸?)
- [七、真正优秀的游戏都在减少 RenderThread 工作量](#七、真正优秀的游戏都在减少 RenderThread 工作量)
- 八、为什么现代游戏都在多线程渲染?
- [九、HarmonyOS 游戏未来为什么一定会走向 Job System?](#九、HarmonyOS 游戏未来为什么一定会走向 Job System?)
- 总结
引言
很多人做 HarmonyOS 游戏优化时,都会经历这样一个阶段。
打开性能工具发现:
text
CPU:30%
GPU:40%
内存正常
看起来一切都很健康,但是:
text
FPS 只有 45
继续降低特效:
text
关闭阴影
降低分辨率
减少粒子
结果:
text
GPU 从 40% 降到 20%
FPS 还是 45
于是很多人开始怀疑人生:
CPU 不忙,GPU 也不忙,为什么游戏还是掉帧?
其实,大部分游戏真正卡住的地方,既不是 CPU,也不是 GPU。而是:
RenderThread(渲染线程)。
很多大型游戏,包括 Unity、UE、Android、HarmonyOS,都会存在同样的问题。
甚至很多时候:
text
CPU 20%
GPU 30%
RenderThread 100%
这才是真正的性能杀手。
一、先理解一帧是怎么出来的
很多人脑海里的流程:
text
CPU
↓
GPU
↓
屏幕
其实真正的流程是:
text
Game Thread
↓
RenderThread
↓
GPU Driver
↓
GPU
↓
Display
Game Thread
负责:
text
AI
物理
动画
状态更新
例如:
ts
update() {
enemySystem.update()
physicsSystem.update()
}
这是逻辑线程。
RenderThread
负责:
text
收集可见对象
排序
Batch
生成 DrawCall
提交 CommandBuffer
例如:
text
Player
Enemy
Tree
Bullet
Particle
全部转换成:
text
DrawCall
再交给 GPU。
GPU
负责真正绘制:
text
Vertex Shader
Fragment Shader
Texture
Rasterization
所以:
text
CPU ≠ GPU
中间还有 RenderThread
很多掉帧都发生在这里。
二、为什么 RenderThread 会成为瓶颈?
因为 GPU 不会直接理解:
text
Player
Enemy
Bullet
UI
GPU 只能理解:
text
CommandBuffer
DrawCall
Vertex Buffer
Texture
因此,游戏世界:
text
Player
Enemy
Tree
Particle
必须经过:
text
RenderThread
转换成:
text
GPU Command
整个过程类似翻译:
text
游戏对象
↓
RenderThread
↓
GPU语言
↓
GPU
如果翻译速度跟不上,GPU 就会等待,于是出现:
text
GPU 利用率很低
FPS 却很低
真正卡住的是:
text
RenderThread
三、RenderThread 每帧都在做什么?
一帧里面,它其实很忙。
1、Visible Culling
判断哪些对象可见:
text
10000 个对象
↓
2000 个可见
例如:
ts
for (obj in world) {
if (camera.contains(obj)) {
visibleList.push(obj)
}
}
这是 CPU 运算。
2、Render Queue 排序
为了减少状态切换,会按照:
text
Material
Texture
Shader
排序:
text
A
A
A
B
B
B
而不是:
text
A
B
A
B
A
否则,GPU 状态切换非常昂贵。
3、Batch
把:
text
1000 个 Sprite
合并成:
text
10 个 DrawCall
例如:
text
Enemy1
Enemy2
Enemy3
Enemy4
text
DrawCall #1
Batch 本身也是 CPU 工作。
4、Command Buffer
生成:
text
DrawIndexed()
BindTexture()
BindShader()
然后提交给 Driver,这一部分全部运行在:
text
RenderThread
四、为什么 DrawCall 太多会卡 RenderThread?
例如,场景中:
text
5000 个对象
每个对象:
text
1 DrawCall
那么:
text
5000 DrawCall
RenderThread 每帧都要:
text
排序
状态切换
生成命令
60FPS 下,每秒:
text
30 万次 DrawCall
CPU 时间大量消耗在:
text
Driver
API Call
于是:
text
RenderThread = 100%
GPU:
text
等待数据
利用率只有:
text
20%
表现出来就是:
GPU 很闲,游戏却很卡。
五、UI 为什么特别容易卡 RenderThread?
这是 HarmonyOS 游戏最容易踩坑的地方,例如:
ts
Column() {
ForEach(items)
}
里面有:
text
1000 个节点
每次:
ts
score++
触发:
text
build()
导致:
text
整个节点树重新布局
重新生成 RenderNode
重新提交
最终,压力全部来到:
text
RenderThread
表现:
text
CPU正常
GPU正常
FPS下降
实际上:
text
RenderThread 爆掉
六、Particle 为什么容易炸?
例如,屏幕上:
text
3000 粒子
每个粒子:
text
位置
旋转
缩放
透明度
都在变化,意味着每帧:
text
VertexBuffer 更新
RenderThread:
text
Upload Buffer
生成 Command
提交 GPU
CPU 开销巨大,所以很多游戏,粒子数量超过:
text
5000
FPS 会瞬间下降,并不是 GPU 不行。而是:
text
RenderThread 来不及提交。
七、真正优秀的游戏都在减少 RenderThread 工作量
核心思想:
让 RenderThread 少干活。
1、Batch
错误:
text
1000 DrawCall
优化:
text
20 DrawCall
2、Atlas
错误:
text
100 张 Texture
优化:
text
1 张大图
减少:
text
BindTexture()
次数。
3、Instancing
例如:
text
1000 棵树
错误:
text
1000 DrawCall
优化:
text
1 DrawCall
GPU 自己复制,RenderThread 几乎不增加负担。
4、缓存静态对象
例如地图,错误每帧:
text
重新生成 Mesh
优化:
text
缓存 VertexBuffer
直接复用。
八、为什么现代游戏都在多线程渲染?
因为单 RenderThread 已经不够用了,传统:
text
GameThread
↓
RenderThread
↓
GPU
RenderThread 成为唯一瓶颈,于是现代引擎开始:
text
GameThread
↓
RenderTask1
RenderTask2
RenderTask3
↓
RenderThread
↓
GPU
例如:
1、Culling 一个线程。
2、Batch 一个线程。
3、Shadow 一个线程。
4、Particle 一个线程。
最后,RenderThread 负责汇总。结构变成:
text
Job System
↓
Worker Thread
↓
RenderThread
↓
GPU
这也是:
text
Unity DOTS
UE5
现代手游
越来越快的原因。
九、HarmonyOS 游戏未来为什么一定会走向 Job System?
因为未来越来越复杂:
text
Agent NPC
大地图
物理
动画
AI
网络同步
全部放在:
text
Main Thread
一定会卡死,未来架构:
text
MainThread
↓
Job System
AI Thread
Physics Thread
Animation Thread
Render Thread
↓
GPU
形成:
text
多核 CPU
↓
并行计算
↓
稳定 120FPS
这也是未来 HarmonyOS 游戏架构的发展方向。
总结
很多开发者看到掉帧时,第一反应是:
GPU 不够强。
实际上大量游戏真正的瓶颈是:
text
RenderThread
因为:
text
CPU
↓
RenderThread
↓
GPU
中间这层,负责把游戏世界翻译成 GPU 能理解的语言。
最后一句话总结:
RenderThread 才是 CPU 和 GPU 之间那座最容易堵车的桥。
很多时候,不是 GPU 画不动。而是:
RenderThread 根本来不及把数据送过去。