[项目分享] Auralis:Signal + Memo + TaskScope —— 一个纯异步 Rust 反应式内核,不是又一个框架
两个 crate,零 unsafe,信号 crate 零外部依赖。不绑 DOM、不碰渲染、没有 view! 宏——你可以把它接到任何 UI 层或数据管线上。
标题句:「反应式 = 可暂停的异步任务;生命周期 = 所有权 + 结构化并发。」
它是什么
auralis-signal:Signal,Memo,memo!宏,SignalMap, batch 更新, 变更检测 future。零外部依赖。auralis-task:TaskScope(结构化并发)、优先级执行器、timer::sleep、上下文依赖注入、panic hook。仅依赖auralis-signal。
use auralis_signal::{Signal, memo};
use auralis_task::{TaskScope, timer};
use std::time::Duration;
let count = Signal::new(0);
let doubled = memo!(count => count.read() * 2); // 宏自动 clone,不用手写
let ex = auralis_task::Executor::new_instance();
let scope = TaskScope::with_executor(&ex); // 显式执行器所有权
scope.spawn(async move {
timer::sleep(Duration::from_secs(1)).await;
count.set(42);
});
drop(scope); // BFS 叶到根取消,200+ 层不爆栈Demo(均可运行)
跟 Leptos / Sycamore 的信号有什么区别
Leptos 的信号是绑死在 DOM 框架里的。Auralis 是纯内核——没有 view!、没有 DOM、没有 hydration。把它理解为「你会用来构建 Leptos 的反应式内核」。
设计上比较有意思的点
延迟回调——
Signal::set()从不同步调用订阅者。通知入队到执行器下一次 flush,彻底消除重入问题。主动 waker 注销——
SignalChangedFuturedrop 时立即从 signal 的订阅列表中移除自己。防止僵尸 waker 堆积——这是异步反应式系统里最容易踩的坑之一。Memo panic 安全——compute 函数 panic 后,旧订阅完好保留。下一次成功
read()即可恢复。迭代式 scope 取消——BFS 收集 + 叶到根取消,零递归,200+ 层嵌套不爆栈。
显式执行器所有权——
TaskScope::with_executor(&ex)持有Rc强引用,spawn/cancel/resume 全部通过 scope 的执行器路由。TaskScope::new()委托到全局执行器作为便利入口。增量 Memo 订阅——重算时共享依赖的订阅保留,只在新增/移除的信号上触发 subscribe/unsubscribe。
信号回调 panic 隔离——每个延迟回调在 executor flush 时被
catch_unwind包裹。故意
!Send + !Sync——Rc代替> Arc。多线程场景用执行器实例隔离。> Slot-based waker 路由——TaskWaker 携带
(slot_id, generation)对,零 unsafe 代码。
性能(500K 行,3 层管道,release)
参数变化率 | 每帧重算 | 手动缓存 | Auralis Memo |
|---|---|---|---|
1%(典型 UI) | ~14 ms | 0.14 ms | 0.16 ms |
10% | ~14 ms | 1.45 ms | 1.78 ms |
50%(最坏) | ~14 ms | 7.33 ms | 9.09 ms |
缓存命中开销 < 0.01ms。真实交互频率下(<1%),Memo 有 ~90x 加速。
链接
crates.io:auralis-signal / auralis-task
文档:https://docs.rs/auralis-signal / https://docs.rs/auralis-task
#![forbid(unsafe_code)],127 测试全绿,clippy 零警告,fmt 洁净。欢迎试用、拍砖、提 issue。