ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

32KB还是1MB:TaskScheduler双层纤程栈池设计与游戏任务栈选择指南

32KB还是1MB:TaskScheduler双层纤程栈池设计与游戏任务栈选择指南 32KB还是1MBTaskScheduler双层纤程栈池设计与游戏任务栈选择指南【免费下载链接】TaskSchedulerCross-platform, fiber-based, multi-threaded task scheduler designed for video games.项目地址: https://gitcode.com/gh_mirrors/tasksch/TaskSchedulerTaskScheduler 是一款跨平台的纤程Fiber多线程游戏任务调度器它用双层纤程栈池巧妙回答了每个游戏引擎开发者都会遇到的难题任务栈给 32KB 还是给 1MB本文带你拆解它的栈池设计与游戏任务栈选择技巧。 先搞懂纤程栈为什么是关键传统多线程中每个线程动辄 1MB 的栈空间开 100 个线程就要 100MB这对内存敏感的游戏来说太奢侈。**纤程Fiber**则不同它运行在线程之上、由调度器协作切换可以拥有极小的独立栈比如 32KB。这意味着✅ 同一线程上可以并行运行成百上千个纤程任务✅ 栈内存可以按需精细分配而不是一刀切 1MB✅ 任务间切换开销远低于线程切换但问题来了栈给小了会栈溢出崩溃给大了又浪费内存。TaskScheduler 的答案是——别二选一两个都要。 双层纤程栈池速览TaskScheduler 在创建调度器时一次性预分配两个纤程池任务按栈需求标签各取所需池类型单个纤程栈大小纤程数量上限池内存占用适用任务标准池STANDARD32 KB256 个8 MBAI、动画、物理子步等绝大多数轻量任务扩展池EXTENDED1 MB8 个8 MB深递归、大局部数组等重型任务工作线程栈1 MB最多 64 条线程按线程数调度器自身与等待逻辑两个池合计16MB 固定开销创建即分配、用完即归还运行期零额外栈分配。 源码拆解双层栈池是怎么实现的1️⃣ 栈大小是编译期常量。四个核心数值定义在 MTScheduler.hMT_STANDART_FIBER_STACK_SIZE 3276832KB× 256 个标准纤程MT_EXTENDED_FIBER_STACK_SIZE 10485761MB× 8 个扩展纤程2️⃣ 栈需求是任务的身份标签。任务类型在声明时就确定了用哪个池枚举定义在 MTStackRequirements.h并通过任务描述结构体携带见 MTTaskDesc.h。声明示例完整用法可看 SimpleTests.cppMT_DECLARE_TASK(MyTask, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);3️⃣ 构造时预建池。在 MTScheduler.cpp 中调度器构造函数循环创建 256 个标准纤程 8 个扩展纤程全部压入两个无锁多生产者多消费者队列LockFreeQueueMPMC供各工作线程无竞争地取用。4️⃣ 任务执行时借纤程结束时还纤程。核心逻辑在RequestFiberContextMTScheduler.cpp按任务的stackRequirements标签从对应队列弹出一个纤程标签是 STANDARD 就只碰标准池是 EXTENDED 就只碰扩展池任务完成后ReleaseFiberContext将其复位并归还原池每个纤程上下文自身也保存了stackRequirements与纤程句柄见 MTFiberContext.h。 游戏任务栈选择指南STANDARD 还是 EXTENDED这是本文最实用的部分——选型口诀默认 STANDARD有证据再升级 EXTENDED。判断维度选 STANDARD32KB选 EXTENDED1MB局部变量少量小对象、指针声明了 KB 级以上的大数组递归深度无递归或浅递归深递归场景树遍历、复杂求值调用链纯引擎内部代码调用第三方库压缩、解析等栈消耗不可控的库并发量同屏成百上千个实体重计算管线同时活跃的很少测试用例 StackSizeTests.cpp 给出了直观参考标准栈任务在栈上开了20000 字节的局部数组32KB 从容胜任扩展栈任务在栈上开了 **262144 字节256KB**的数组只有 1MB 栈能装下⚠️进阶提醒栈占用还会受编译器影响。测试代码中特意注释了OSX 下 ASan 占用了过多栈空间所以开启 sanitizer 调试时标准栈任务可能需要临时放大栈占用预算不要盲目相信 release 下的测量值。⚠️ 别忽略池耗尽是隐性并发上限双层设计还带来一个容易被新手忽略的天花板同一时刻最多256 个STANDARD 任务在飞同一时刻最多8 个EXTENDED 任务在飞一旦池空调度器会直接断言失败Cant get more standard fibers! ... Too many tasks in flight simultaneously?MTScheduler.cpp。实操建议 如果你的玩法要同屏并行几千个 AI/物理任务考虑拆分任务粒度每帧处理一个实体批次而不是一股脑全丢进队列 EXTENDED 池只有 8 个名额把它留给真正吃栈的少数派若发现 8 个不够说明任务设计该优化了 上线前用栈占用分析工具实测每个任务类型的峰值栈深这是从拍脑袋到有依据的质变 内存账本你的调度器到底占了多少内存以8 核 CPU7 个工作线程 完整纤程池为例项目计算内存标准纤程池256 × 32KB8 MB扩展纤程池8 × 1MB8 MB工作线程栈7 × 1MB7 MB合计约 23 MB对比为 100 个并行任务开 100 条 1MB 栈线程的 100MB 方案纤程方案省了近4 倍内存——这正是双层栈池设计的核心价值用最小的常驻成本覆盖 32KB 到 1MB 的全部栈需求区间。✅ 速查清单✅90% 的任务选 STANDARD局部变量小、无深递归、可高频并发✅少数重型任务选 EXTENDED大栈数组、深递归、第三方库调用✅ 栈需求在MT_DECLARE_TASK宏中编译期声明无需运行时判断✅ 记住隐性上限256 个标准并发 / 8 个扩展并发✅ 调度器固定开销约 16MB 纤程栈 每工作线程 1MB✅ 调试期ASan 等栈占用会膨胀选型测量以 release 配置为准 延伸阅读项目 README.md 中整理了 Naughty Dog 纤程引擎 GDC 演讲、Ubisoft 多线程开发、Enki Task Scheduler 等业界经典资料是理解这套纤程调度思想的绝佳入口。【免费下载链接】TaskSchedulerCross-platform, fiber-based, multi-threaded task scheduler designed for video games.项目地址: https://gitcode.com/gh_mirrors/tasksch/TaskScheduler创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表