Skip to content

Compile Configuration

dgliu edited this page Feb 14, 2026 · 1 revision

编译期配置

MCCC 通过编译期宏实现零成本硬件适配。所有配置在编译时确定,不产生运行时分支开销。


配置宏一览

宏名 默认值 说明
MCCC_QUEUE_DEPTH 131072 环形缓冲区深度 (必须为 2 的幂)
MCCC_CACHELINE_SIZE 64 缓存行大小 (字节),用于 padding 防伪共享
MCCC_SINGLE_PRODUCER 0 设为 1 启用 SPSC 模式 (wait-free)
MCCC_SINGLE_CORE 0 设为 1 启用单核模式 (relaxed 内存序)
MCCC_MAX_MESSAGE_TYPES 8 单条总线支持的最大消息类型数
MCCC_MAX_CALLBACKS_PER_TYPE 16 每种消息类型的最大回调数
MCCC_MAX_SUBSCRIPTIONS_PER_COMPONENT 16 每个 Component 的最大订阅数
STREAMING_DMA_ALIGNMENT 64 DMA 缓冲区对齐 (字节)

详细说明

MCCC_QUEUE_DEPTH

环形缓冲区的槽位数量。必须为 2 的幂次方 (编译期 static_assert 检查),因为内部使用位掩码 (depth - 1) 替代取模运算。

推荐值:
- 服务器/工控:  131072 (128K, 默认)
- 资源受限 Linux: 32768 或 65536
- 嵌入式 MCU:    1024 或 4096

每个槽位的大小等于 sizeof(MessageEnvelope<PayloadVariant>)。总内存占用 = MCCC_QUEUE_DEPTH * sizeof(Envelope)

MCCC_CACHELINE_SIZE

用于在环形缓冲区的读写索引之间插入 padding,防止伪共享 (false sharing)。

推荐值:
- x86-64 / ARM Cortex-A: 64
- 无 D-Cache 的 MCU:     0 (关闭 padding,节省 RAM)

设为 0 时,不插入任何 padding,适用于无数据缓存的单核 MCU (如 Cortex-M0/M3)。

MCCC_SINGLE_PRODUCER

模式 入队策略 说明
0 MPSC CAS 自旋 (指数退避) 多生产者安全,有 CAS 竞争开销
1 SPSC wait-free 直接写入 单生产者专用,无原子 RMW 操作

SPSC 模式下入队操作为 wait-free (非 lock-free),延迟确定性更好。但调用者必须保证仅有一个线程执行 Publish()

MCCC_SINGLE_CORE

内存序 屏障 说明
0 acquire/release 硬件 DMB (ARM) 或 MFENCE (x86) 多核安全
1 relaxed + signal_fence 编译器屏障,无硬件屏障 仅单核安全

安全警告: 启用 MCCC_SINGLE_CORE=1 时,必须同时定义 MCCC_I_KNOW_SINGLE_CORE_IS_UNSAFE=1,否则编译失败。这是一个防呆机制,确保开发者明确理解:

  • 单核模式的 relaxed 内存序在多核 CPU 上会导致数据竞争
  • 仅适用于真正的单核 MCU (如 Cortex-M0/M3/M4) 或已确认绑定单核的场景
  • ISR 与主循环之间的通信是安全的 (atomic_signal_fence 防止编译器重排)
// 启用单核模式必须同时定义两个宏
#define MCCC_SINGLE_CORE 1
#define MCCC_I_KNOW_SINGLE_CORE_IS_UNSAFE 1

MCCC_MAX_MESSAGE_TYPES

回调表 (DispatchTable) 的行数。每种消息类型占一行。超过此限制时 Subscribe() 返回失败。

MCCC_MAX_CALLBACKS_PER_TYPE

回调表每一行的列数。同一消息类型最多注册的回调数量。超过此限制时 Subscribe() 返回失败。

MCCC_MAX_SUBSCRIPTIONS_PER_COMPONENT

Component 基类内部用 FixedVector 追踪已注册的订阅 ID,容量由此宏控制。超出时 SubscribeSafe()/SubscribeSimple() 返回失败。

STREAMING_DMA_ALIGNMENT

DMA 传输缓冲区的对齐要求。用于需要 DMA 拷贝的场景 (如共享内存传输)。


嵌入式 MCU 推荐配置

针对资源受限的嵌入式 MCU (如 ARM Cortex-M4, 128KB~512KB SRAM):

add_definitions(
    -DMCCC_QUEUE_DEPTH=1024
    -DMCCC_CACHELINE_SIZE=0
    -DMCCC_SINGLE_PRODUCER=1
    -DMCCC_SINGLE_CORE=1
    -DMCCC_I_KNOW_SINGLE_CORE_IS_UNSAFE=1
    -DMCCC_MAX_MESSAGE_TYPES=4
    -DMCCC_MAX_CALLBACKS_PER_TYPE=4
    -DMCCC_MAX_SUBSCRIPTIONS_PER_COMPONENT=8
    -DSTREAMING_DMA_ALIGNMENT=4
)

内存占用估算 (假设 sizeof(Envelope) = 128 字节):

  • 环形缓冲区: 1024 * 128 = 128 KB
  • 回调表: 4 * 4 * 8 = 128 字节
  • 总计: 约 128 KB

如果 SRAM 紧张,可进一步降低 MCCC_QUEUE_DEPTH 至 256 或 512。


CMake 构建示例

默认配置 (服务器/工控)

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

自定义编译期配置

cmake -B build \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_CXX_FLAGS="-DMCCC_QUEUE_DEPTH=65536 -DMCCC_SINGLE_PRODUCER=1"
cmake --build build -j$(nproc)

MCU 交叉编译 (ARM Cortex-M4 示例)

cmake -B build \
    -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi.cmake \
    -DCMAKE_BUILD_TYPE=MinSizeRel \
    -DCMAKE_CXX_FLAGS="\
        -DMCCC_QUEUE_DEPTH=1024 \
        -DMCCC_CACHELINE_SIZE=0 \
        -DMCCC_SINGLE_PRODUCER=1 \
        -DMCCC_SINGLE_CORE=1 \
        -DMCCC_I_KNOW_SINGLE_CORE_IS_UNSAFE=1 \
        -fno-exceptions -fno-rtti"
cmake --build build -j$(nproc)

SPSC vs MPSC 模式选择

多个线程/ISR 调用 Publish()?
    |
    +-- 是 --> MCCC_SINGLE_PRODUCER=0 (MPSC, CAS 自旋)
    |
    +-- 否 --> MCCC_SINGLE_PRODUCER=1 (SPSC, wait-free)
                |
                +-- 吞吐量提升约 14%
                +-- 延迟确定性更好 (无 CAS 重试)
                +-- 尾延迟 (P99) 大幅降低

SPSC 模式的典型应用场景:

  • 单一采集线程 -> 处理线程 的数据管道
  • ISR -> 主循环 的事件通知 (配合 MCCC_SINGLE_CORE=1)
  • 单一网络接收线程 -> 业务逻辑线程 的解耦

运行时性能模式

除编译期配置外,MCCC 还支持运行时切换性能模式:

auto& bus = AsyncBus<MyPayload>::Instance();
bus.SetPerformanceMode(PerformanceMode::BARE_METAL);
模式 背压 统计 错误回调 适用场景
FULL_FEATURED 开发调试,生产监控
BARE_METAL 极致性能,嵌入式裸机
NO_STATS 生产环境,需要背压保护

运行时模式可随时切换。模式切换本身是原子操作 (单个 store),不会引入竞争。

BARE_METAL 模式关闭所有运行时检查,适合已充分验证的生产部署或对延迟极度敏感的场景。在此模式下:

  • Publish() 不检查背压,不更新统计计数器
  • 队列满时消息静默丢弃,不触发错误回调
  • GetStatistics() 返回全零快照