open-coroutine
是一个简单、高效、通用的有栈协程库,您可以将其用作IO线程池的性能替代,查看为什么更好.
English | 中文
- 抢占调度(
不支持windows
): 即使协程进入死循环,它仍能被抢占,查看例子; - Hook: 您可以在协程中自由使用大多数慢系统调用,查看支持的系统调用unix/windows;
- 可伸缩栈: 协程栈的大小支持无限制扩容而没有复制堆栈的开销,查看例子;
- io_uring(
只支持linux
): 在本地文件IO和网络IO方面支持并兼容io_uring。如果您的系统不支持,它将回退到NIO; - 优先级: 支持自定义任务优先级,注意协程优先级未对用户开放;
- 任务窃取: 内部使用无锁任务窃取队列;
- 兼容性: open-coroutine的实现是No async的,但它与async兼容,这意味着您可以在
tokio/sync-std/smol/...
中使用这个crate; - 跨平台: 支持Linux、macOS和Windows;
- 增加性能基准测试;
- 取消协程/任务;
- 增加性能指标;
- 增加并发工具包;
- 支持AF_XDP套接字;
graph TD
subgraph ApplicationFramework
Tower
Actix-Web
Rocket
warp
axum
end
subgraph MessageQueue
RocketMQ
Pulsar
end
subgraph RemoteProcedureCall
Dubbo
Tonic
gRPC-rs
Volo
end
subgraph Database
MySQL
Oracle
end
subgraph NetworkFramework
Tokio
monoio
async-std
smol
end
subgraph open-coroutine-architecture
subgraph core
Preemptive
ScalableStack
WorkSteal
Priority
end
subgraph hook
HookSyscall
end
subgraph macros
open-coroutine::main
end
subgraph open-coroutine
end
hook -->|depends on| core
open-coroutine -->|link| hook
open-coroutine -->|depends on| macros
end
subgraph OperationSystem
Linux
macOS
Windows
end
ApplicationFramework -->|maybe depends on| RemoteProcedureCall
ApplicationFramework -->|maybe depends on| MessageQueue
ApplicationFramework -->|maybe depends on| Database
MessageQueue -->|depends on| NetworkFramework
RemoteProcedureCall -->|depends on| NetworkFramework
NetworkFramework -->|runs on| OperationSystem
NetworkFramework -->|can depends on| open-coroutine-architecture
Database -->|runs on| OperationSystem
open-coroutine-architecture -->|runs on| OperationSystem
[dependencies]
# check https://crates.io/crates/open-coroutine
open-coroutine = "x.y.z"
#[open_coroutine::main]
fn main() {
//......
}
#[open_coroutine::main]
fn main() {
_ = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param");
}
#[open_coroutine::main]
fn main() {
_ = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param", 1/*数值越小,优先级越高*/);
}
#[open_coroutine::main]
fn main() {
let task = open_coroutine::task!(|param| {
assert_eq!(param, "param");
}, "param", 1);
task.timeout_join(std::time::Duration::from_secs(1)).expect("timeout");
}
#[open_coroutine::main]
fn main() {
_ = open_coroutine::task!(|_| {
fn recurse(i: u32, p: &mut [u8; 10240]) {
open_coroutine::maybe_grow!(|| {
// Ensure the stack allocation isn't optimized away.
unsafe { _ = std::ptr::read_volatile(&p) };
if i > 0 {
recurse(i - 1, &mut [0; 10240]);
}
})
.expect("allocate stack failed")
}
println!("[task] launched");
// Use ~500KB of stack.
recurse(50, &mut [0; 10240]);
}, ());
}
这个crate的灵感来自以下项目:
感谢那些提供帮助的人: