动手
前面各部分读的是 embassy 的源码。这一部分反过来:不依赖 embassy,只用 core、critical-section 和 cortex-m,把定时器主线和跨任务主线需要的那几样东西自己写一遍。写完之后在 std 和 QEMU 上跑同一对任务,再把同样的任务放到 embassy 上,比体积和 poll 次数。
- 写一个迷你执行器:库 474 行代码。任务放在定长的字节格子里,执行器只记一个类型擦除的
poll_fn,future 放不下是单态化时的编译错误,cargo check看不到;运行队列是一个u32位图,一条fetch_or同时去重和决定要不要SEV,批内按槽号出队;waker 是格子头指针加一张静态 vtable;时钟每毫秒 tick 一次,定时器表按到期时刻排序,只看表头。生产者、消费者经容量为 1 的 channel 通信,日志在 std、QEMU 和 embassy 上完全相同;同一 tick 两个任务同时到期时,mini 先跑槽号小的、embassy 先跑先登记的,生产者因此多 poll 一次(11 对 10)。QEMU 上 mini 和 embassy 的.text只差 100 字节,只换执行器差 76 字节;rotate拉进的 1410 字节memmove、把 future 当参数传进async fn后大小翻倍,都比执行器本身的差别大。最后一张表列出 embassy 多出来的东西(按任务定大小的池、原地构造、不限任务数的队列、可替换的时间驱动、InterruptExecutor、调度策略)和讲它们的页。
flowchart TB slot["任务槽"] --> mask["位图运行队列"] mask --> waker["手写 waker"] clock["时钟 定时器表"] --> waker chan["Channel"] --> waker waker --> std["std 条件变量"] waker --> qemu["QEMU WFE"] qemu --> cmp["和 embassy 比"]
💬 关联讨论
发起讨论加载中...