最佳实践(Best Practices)
本节给出在使用 koroutine_lib 时的若干建议,覆盖协程生命周期、取消、调度器选择、性能调优与调试技巧。
1. 协程生命周期与结构化并发
- 优先使用
when_all/Runtime::join_all等结构化并发原语来限定协程的生命周期,避免“火箭发射器式”的后台任务(无控制的长期驻留任务)。 - 对于短生命周期的辅助任务,使用
details::FireAndForget或者明确start()并保证在作用域退出前有合适的取消/等待逻辑。
2. 取消(Cancellation)
- 使用库提供的
CancellationToken(见include/koroutine/cancellation.hpp)进行合作式取消,而不是强行终止线程。 - 在可能长时间挂起的 awaiter(IO/睡眠/Channel)处检测取消标志并尽早返回。
3. 调度器与执行器选择
- 默认调度器:
SchedulerManager::get_default_scheduler()返回的默认调度器使用ThreadPoolExecutor,适合大多数 CPU 密集型和通用任务。 - IO 隔离: 如果有大量阻塞 IO 操作,建议创建一个独立的
SimpleScheduler实例作为 IO 调度器,避免阻塞默认的计算线程池。 - 线程亲和性: 对于需要线程亲和性(如访问非线程安全资源或 UI 更新),可以使用
LooperExecutor并通过co_await switch_to(looper_scheduler)切换到该上下文。你需要手动创建使用LooperExecutor的调度器。
4. 性能分析 (Profiling)
为了确保你的协程应用达到最佳性能,建议定期进行性能分析。
构建配置
在进行性能分析之前,请确保使用 RelWithDebInfo 模式构建项目。这既能开启优化,又能保留调试符号,方便定位热点函数。
macOS 平台分析工具
在 macOS 上,你可以使用以下工具:
-
Instruments (Time Profiler): Xcode 自带的强大图形化分析工具。
- 打开 Instruments (
Cmd+Iin Xcode, or open separately). - 选择 "Time Profiler".
- 选择你的可执行文件并开始录制。
- 分析调用栈,找出耗时最长的函数。
- 打开 Instruments (
-
这会采样 10 秒并将结果输出到sample命令行工具: 如果你只需要快速查看运行中进程的采样:output.txt。
Linux 平台分析工具
在 Linux 上,perf 是最常用的工具:
通过火焰图 (FlameGraph) 可以更直观地查看协程调度和业务逻辑的开销分布。
- 减少频繁的
start()/resume()切换,尽量把短任务合并在同一协程内完成; - 避免在执行器线程内做大量阻塞操作,除非该执行器专门用于阻塞 I/O;
- 对于高频调用路径,考虑减少堆分配和 std::function 的动态分配(可以在未来用 folly/boost 的小函数优化替代);
5. 调试与日志
- 启用
KOROUTINE_DEBUG宏可以打印更详细的运行时信息(见include/koroutine/debug.h); - 使用
ScheduleMetadata::debug_name在调度点传递可读的任务标识,以便在日志中归因。
6. API 兼容性与版本策略
- 如果你计划将来支持 C++26 的
std::execution能力,建议在库中增加适配层(adapter),而不是把内部实现替换为std::execution。 - 保持
Task/Awaiter的 API 稳定,避免在 minor 版本中破坏调用约定。