LwEVT轻量够用的广播分发器,microbus是稍大功能更全的事件总线
声明: microbus 与 LwEVT 都是开源项目。microbus 的作者是 Peter Vanderhell,LwEVT 的作者是 Tilen MAJERLE。本文是对两个项目源码做 ARM GCC 编译与资源实测后整理的对比笔记。本文作者不是这些项目的开发者,未参与任何代码贡献。 文中资源数据来自编译实测,工程细节来自对开源代码的分析,不代表本文作者的设计决策。
项目仓库:
- microbus:github.com/Vanderhell/microbus,话题事件总线
- LwEVT:github.com/MaJerle/LwEVT,极简事件分发器
结论
两个库都无需堆分配,可直接集成进 Cortex-M 工程。LwEVT 用 170 B 代码和 48 B RAM 完成广播分发:注册回调后 dispatch 逐个调用,携带数据的类型由 X-macro 在编译期生成。microbus 用 972 B 代码和 544 B RAM 提供完整事件总线:话题过滤、通配订阅、payload 拷贝、有界队列、确定性分发、错误码与 ABI 校验。资源差距来自功能差距,两者都在各自定位内把代价花在该花的地方。选型看需求:只要求通知一组回调、偶尔带点数据,LwEVT 够用;需要话题路由、ISR 入队、多实例或错误诊断,选 microbus。
两库结构对比如下:microbus 把订阅表和环形队列放进调用者持有的 mbus_t,按话题过滤分发;LwEVT 用全局静态监听表做广播,监听器自行按 type 过滤。
资源占用对比(Cortex-M4 实测)
工具链 arm-none-eabi-gcc 14.3.1,Cortex-M4,-Os,链接 --gc-sections;完整程序为库加对等功能测试程序加 crt0。两库均通过 -Wall -Wextra -Werror 零告警。
| 指标 | microbus | LwEVT |
|---|---|---|
| 库代码(单个 .o,全 API) | 972 B | 170 B |
| 库静态 RAM | 0 B(状态由调用者持有) | 48 B(全局单例) |
| 事件对象 | mbus_event_t 40 B | LwEVT_t 12 B |
| 订阅/监听表 | 16 槽 × 12 B = 192 B | 8 槽 × 4 B = 32 B |
| 完整总线实例 RAM | mbus_t 544 B(订阅表 192 + 队列 320 + 杂项 32) | 48 B |
| 最小配置 | 关队列后 1072 B text | 关默认句柄后 668 B text |
| 最大函数体 | mbus_dispatch 132 B | LwEVT_register 60 B |
关键解读:microbus 的 544 B RAM 由调用者决定占用位置,放栈或静态都行,关掉队列再省约 328 B;LwEVT 的 48 B 是编译进去就固定的全局量,关默认句柄可降到 36 B。
microbus 的设计收益
- 实例化设计:
mbus_t由调用者持有,可多实例、放栈上,测试隔离容易 - 话题过滤:uint8 话题加
MBUS_TOPIC_ANY通配订阅,回调只收到匹配事件 - payload 拷贝进事件对象,调用方的临时缓冲可以立刻复用
- 有界队列:环形缓冲、深度为 2 的幂;
mbus_dispatch入口快照队列长度,回调里再入队不会让本次分发无限执行 - 确定性:投递期间修改订阅表返回
MBUS_ERR_BUSY,升序遍历保证顺序 - 错误契约:8 个错误码加
mbus_err_str();mbus_impl_init用sizeof(*bus)校验 ABI - 可裁剪:关队列省约 328 B RAM,
MBUS_ISR_SAFE_QUEUE模式配临界区钩子支持 ISR 入队
LwEVT 的设计收益
- X-macro 类型系统:在
LwEVT_types.h声明LwEVT_TYPE_BASIC/LwEVT_TYPE_EXT,编译期生成枚举和数据 union,事件类型与携带数据绑定 - 零拷贝:监听器直接读写句柄里的 union,不复制 payload
- API 只有 5 个函数,注册自动去重
- 可关默认句柄再省 12 B
- 代价:全局单例、无法退订、无队列、错误只回 0/1、无并发保护
选型依据
- 场景 A:Flash 只剩几百字节,只做简单事件广播,选 LwEVT。170 B 代码加 48 B RAM,接近免费。
- 场景 B:需要话题过滤、ISR 入队延迟处理、多实例或错误诊断,选 microbus。972 B 代码,RAM 按需实例化。
- 判断句:能接受所有监听器收所有事件、自行按 type 过滤,LwEVT 够用;出现只关心某类话题、或中断里发事件主循环处理的需求,就换 microbus。
- 边界:LwEVT 无法退订是实际限制;microbus 的话题空间只有 256 个、payload_len 是单字节,都是容量上限。