YuuFrag学习记录 共享笔记库
与你的相遇就是奇迹

定义 ProfilerEvent —— 把一次 profiler 的行为打包,形成一个固定格式,而不是随意乱写的数据(
struct alignas(8) ProfilerEvent
{
uint64_t timestampNs = 0;
uint64_t frameId = kInvalidProfilerFrameId;
uint64_t payload = 0;
uint32_t threadId = 0;
uint32_t nameId = kInvalidProfilerNameId;
ProfilerEventType type = ProfilerEventType::Instant;
ProfilerEventFlags flags = ProfilerEventFlags::None;
uint16_t reserved = 0;
};
其中 ——
timestampNs 时间戳,记录事件发生的时间frameId 记录事件发生的那一帧payload 不同的事件有不同的语义 —— 记录数据使用threadId 记录事件来自的线程IDnameId 记录事件关联的名字(只记录 id 避免字符串转发)type 表示事件类型flags 表示事件附加信息reserved 为未来的拓展预留一块enum class ProfilerEventType : uint8_t
{
// 帧标记,例如 frame begin / frame end。
FrameMark,
// CPU zone 开始。
ZoneBegin,
// CPU zone 结束。
ZoneEnd,
// 数值采样。
Counter,
// 瞬时事件。
Instant,
// 线程命名事件。
ThreadName,
};
直接在注释说明,特别的
此处使用uint8_t,大小为一个字节
enum class ProfilerEventFlags : uint8_t
{
// 没有特殊标记。
None = 0,
// 当前 FrameMark 是 frame begin。
// 1u << 0u = 0000'0001
FrameBegin = 1u << 0u,
// payload 里面装的是 double 的 bit pattern。
// 1u << 1u = 0000'0010
FloatingPointPayload = 1u << 1u,
};
可以未来接上新的拓展标记之类的,不过当前代码里主要用到的是区分 ——
FrameMark 是否是 frame beginpayload 是否是 double不过当前的代码中没有为 ProfilerEventFlags 定义 operator| / operator&。因此从这个模块本身来看,它更像是单 flag 使用;如果未来需要组合多个 flag,可以补充对应的位运算重载或显式转换。
在声明 ProfilerEvent 的时候使用了 alignas(8) 使得结构体至少按照 8 字节对齐,而 ——
uint64_t timestampNs 8
uint64_t frameId 8
uint64_t payload 8
uint32_t threadId 4
uint32_t nameId 4
ProfilerEventType 1
ProfilerEventFlags 1
uint16_t reserved 2
先说明一下字段的定义,和 Session 比较简单的零碎边缘,把内部的具体实现留到下次说明
聚焦外部调用 BeginFrame / BeginZone / RecordCounter / RecordInstant 后,Session 如何构造事件,并把它交给下一层,即 ——
说明多线程中,每个线程获得和维护自己的 profiler threadId 和事件 buffer
拆分Profiler中的宏定义和展开这块的内容 ——
把 ProfilerScope 和 ProfilerFrameScope 做一次 RAII 封装,保证有Begin就一定有End