3个版本
0.1.2 | 2024年2月22日 |
---|---|
0.1.1 | 2024年2月22日 |
0.1.0 | 2024年2月22日 |
#394 in 异步
在2个crates中使用(通过lock_pool)
78KB
1K SLoC
ref_count
ref_count
是一个高性能、健壮的no_std
、no_alloc
异步引用计数crate,适用于需要效率和低开销的Rust环境。它利用核心futures和核心wakers,以及无锁队列,来管理无需阻塞或自旋的同步,非常适合用于嵌入式系统、实时应用或任何动态内存分配和标准库功能不可用或不希望使用的场景。
特性
- 高性能:针对资源有限的环境进行优化,以提高速度和效率。
- 健壮性:精心实现,确保线程安全,没有死锁,尤其是在处理独占引用时,已通过
loom
等手段验证。 no_std
和no_alloc
:在no_std
环境中工作,无需动态内存分配。- 异步:使用核心库中的futures和wakers来处理等待,无需阻塞或自旋。
- 独占引用:支持独占引用,允许创建更高级的原始数据,如读者-写入者锁。
- 公平:利用无锁队列,防止优先级反转和饥饿。
- 环境无关:从seL4到Linux,此crate被设计为不关心。这也适用于异步运行时,与您的偏好无关。
安装
将ref_count
添加到您的Cargo.toml
[dependencies]
ref_count = "0.1.2"
示例用法
创建一个RwLock
use ref_count::{RefCount, Ref, ExclusiveRef, maybe_await};
use core::cell::UnsafeCell;
const MAX_WAITERS: usize = 32;
struct RwLock<T> {
data: UnsafeCell<T>,
state: RefCount<MAX_WAITERS>
}
struct ReadGuard<'lock, T> {
_ref: Ref<'lock, MAX_WAITERS>,
data: &'lock T
}
struct WriteGuard<'lock, T> {
_ref: ExclusiveRef<'lock, MAX_WAITERS>,
data: &'lock mut T
}
impl<T> RwLock<T> {
fn new(t: T) -> Self {
Self {
data: UnsafeCell::new(t),
state: RefCount::new()
}
}
async fn read(&self) -> ReadGuard<T> {
let r = maybe_await!(self.state.get_ref());
ReadGuard {
_ref: r,
// SAFETY: Multiple read guards can be created as `RefCount` ensures that
// no exclusive references are granted when shared references exist.
data: unsafe { &*self.data.get() }
}
}
async fn write(&self) -> WriteGuard<T> {
let e = maybe_await!(self.state.get_exclusive_ref());
WriteGuard {
_ref: e,
// SAFETY: Only one `WriteGuard` can be created at a time as `RefCount` ensures
// exclusive access to the data.
data: unsafe { &mut *self.data.get() }
}
}
}
行动中的简洁
上述示例在不到两分钟内完成,突出了ref_count
设计的简单性和用户友好性。这种简单性是该库哲学的核心,确保开发者可以轻松实现稳健、no_std
、no_alloc
、异步引用计数的功能,学习曲线平缓。无论在嵌入式系统、实时应用或其他效率关键环境中,ref_count
都旨在简化开发过程,同时保持高性能和安全标准。
性能重点:标准引用与独占引用
在ref_count
的开发过程中,观察到在许多应用中,尤其是那些使用读写锁的应用中,读操作的频率远超过写操作。这一模式并非偶然,而是从文件系统到数据库管理等多个领域的广泛记录现象。基于这一洞察,ref_count
被刻意设计以在这些常见场景中表现出色,从而确保最频繁执行的操作也是最有效的。
通过专注于提高获取和释放标准引用的性能,ref_count
将这些操作的性能提升了超过50%,与主要竞争对手相比。对于独占引用,设计优先考虑等待线程的获取速度和效率,而不仅仅是释放操作的效率。
优点
- 优化的读操作:提供对更常见读操作的快速访问,从而提高整体应用性能。
- 良好的写访问管理:确保写操作的效率和公平性,有助于系统的稳定性和可靠性。
- 通用性:设计用于适应各种应用,从主要需要读访问的应用到需要及时写访问的应用。
依赖关系
~0–24MB
~335K SLoC