跳转至

TinyBench 设计说明

设计动机

在嵌入式 SHM 节点上,数据和算法模块分散在不同的函数和全局变量中。外部 Agent 或用户无法在运行时发现:

  • 当前有什么数据?采集结果存在哪里?
  • 有什么工具可用?每个工具输入输出是什么?

TinyBench 解决这个问题——它是一个运行时可查询的命名注册表,把内存地址映射为名字,把不可见变为可发现。

核心设计决策

零拷贝

tiny_bench_put() 只存数据指针,不复制数据。调用者负责管理内存生命周期。这对嵌入式系统至关重要——避免在采集→处理→分析的每条路径上额外拷贝。

静态分配

所有表在 tiny_bench_init() 时清零,运行时零堆分配。配置宏(TINY_BENCH_MAX_DATA 等)决定表容量,编译时固定。

类型安全

每个数据槽和工具都带 tiny_type_t 类型标签。TinyOrch 在 step() 定义时做类型校验(src.type == tool.in_type),把错误暴露在执行之前。

数据槽 vs 工具注册表

数据槽 工具注册表
管理什么 处理过程中的数据 可调用的处理函数
生命周期 动态(put / remove) 静态(初始化时注册)
查询 list_data() list_tools(), tool_info()
MQTT BENCH,DATA BENCH,TOOLS, BENCH,TOOL,name

典型使用模式

1. 初始化 + 注册

系统启动时注册所有工具,这些工具在后续运行中不变:

tiny_bench_t bench;
tiny_bench_init(&bench);

tiny_bench_register_tool(&bench, "butterworth", fn_bw,
    TINY_TYPE_F32_ARR, TINY_TYPE_F32_ARR);
tiny_bench_register_tool(&bench, "fft", fn_fft,
    TINY_TYPE_F32_ARR, TINY_TYPE_CF32_ARR);

2. 运行时数据流

采集任务把数据放到工作台上,流程引擎读取并处理:

// 采集线程
tiny_bench_put(&bench, "raw_0", adxl_buffer, N * sizeof(float), TINY_TYPE_F32_ARR);

// 流程执行
void *data; size_t len; tiny_type_t type;
tiny_bench_get(&bench, "raw_0", &data, &len, &type);
// → 拿到 adxl_buffer 指针,零拷贝

3. Agent 远程查询

→ /mqtt/server: BENCH,TOOLS
← /mqtt/node:   BENCH,TOOLS,4,butterworth:f32[]→f32[],fft:...

Agent 先查有什么工具和数据,再决定编排哪种流程。

设计约束

  • 名称长度: TINY_BENCH_NAME_LEN(默认 24),含 \0
  • 表满拒绝: 数据槽或工具数超限时返回 ERR_FULL,不静默丢弃
  • 线程安全: 当前版本不内置锁。单任务场景(MQTT 回调 + 采集任务通过消息队列)无需锁
  • 数据不持久化: bench 纯运行时,重启后需重新 put 数据和注册工具