Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,33 @@
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Percentage of issues still open")

The `open-coroutine` is a simple, efficient and generic stackfull-coroutine library, you can use this as a performance replacement for IO thread pools.
The `open-coroutine` is a simple, efficient and generic stackfull-coroutine library, you can use this as a performance
replacement for IO thread pools, see [why better](core/docs/en/why-better.md).

English | [中文](README_ZH.md)

## 🚀 Features

- [x] Preemptive(`not supported in windows`): even if the coroutine enters a dead loop, it can still be seized, see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs);
- [x] Hook: you are free to use most of the slow syscall in coroutine, see supported syscall on [unix](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/unix.rs)/[windows](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/windows.rs);
- [x] Scalable: the size of the coroutine stack supports unlimited expansion without the cost of copying stack, and immediately shrinks to the original size after use, see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs);
- [x] io_uring(`only in linux`): supports and is compatible with io_uring in terms of local file IO and network IO. If it's not supported on your system, it will fall back to non-blocking IO;
- [x] Preemptive(`not supported in windows`): even if the coroutine enters a dead loop, it can still be seized,
see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs);
- [x] Hook: you are free to use most of the slow syscall in coroutine, see supported syscall
on [unix](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/unix.rs)/[windows](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/windows.rs);
- [x] Scalable: the size of the coroutine stack supports unlimited expansion without the cost of copying stack, and
immediately shrinks to the original size after use,
see [example](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs);
- [x] io_uring(`only in linux`): supports and is compatible with io_uring in terms of local file IO and network IO. If
it's not supported on your system, it will fall back to non-blocking IO;
- [x] Priority: support custom task priority, note that coroutine priority is not open to users;
- [x] Work Steal: internally using a lock free work steal queue;
- [x] Compatibility: the implementation of open-coroutine is no async, but it is compatible with async, which means you can use this crate in `tokio/async-std/smol/...`;
- [x] Compatibility: the implementation of open-coroutine is no async, but it is compatible with async, which means you
can use this crate in `tokio/async-std/smol/...`;
- [x] Platforms: running on Linux, macOS and Windows;

## 🕊 Roadmap

- [ ] add docs;
- [ ] add performance [benchmark](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview);
- [ ] add
performance [benchmark](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview);
- [ ] cancel coroutine/task;
- [ ] add metrics;
- [ ] add synchronization toolkit;
Expand Down Expand Up @@ -79,7 +87,7 @@ graph TD
subgraph open-coroutine
end
hook -->|depends on| core
open-coroutine -->|depends on| hook
open-coroutine -->|link| hook
open-coroutine -->|depends on| macros
end
subgraph OperationSystem
Expand Down Expand Up @@ -179,11 +187,12 @@ fn main() {
## ⚓ Learn More

- [Coroutine Overview](core/docs/en/coroutine.md)
- [Scalable Stack Overview](core/docs/en/scalable-stack.md)
- [Monitor Overview](core/docs/en/monitor.md)

[我有故事,你有酒吗?](https://github.com/acl-dev/open-coroutine-docs)

## 🙏 Credits
## 👍 Credits

This crate was inspired by the following projects:

Expand All @@ -194,3 +203,10 @@ This crate was inspired by the following projects:
- [monoio](https://github.com/bytedance/monoio)
- [compio](https://github.com/compio-rs/compio)
- [may](https://github.com/Xudong-Huang/may)

Thanks to those who have provided assistance:

![Amanieu](https://images.weserv.nl/?url=avatars.githubusercontent.com/Amanieu?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![bjorn3](https://images.weserv.nl/?url=avatars.githubusercontent.com/bjorn3?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![workingjubilee](https://images.weserv.nl/?url=avatars.githubusercontent.com/workingjubilee?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![Noratrieb](https://images.weserv.nl/?url=avatars.githubusercontent.com/Noratrieb?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
29 changes: 20 additions & 9 deletions README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "解决issue的平均时间")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "仍未关闭issue的百分比")

`open-coroutine`是一个简单、高效、通用的有栈协程库,您可以将其用作IO线程池的性能替代
`open-coroutine`是一个简单、高效、通用的有栈协程库,您可以将其用作IO线程池的性能替代,查看[为什么更好](core/docs/en/why-better.md).

[English](README.md) | 中文

## 🚀 当前特性

- [x] 抢占调度(`不支持windows`): 即使协程进入死循环,它仍能被抢占,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs);
- [x] Hook: 您可以在协程中自由使用大多数慢系统调用,查看支持的系统调用[unix](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/unix.rs)/[windows](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/windows.rs);
- [x] 可伸缩栈: 协程栈的大小支持无限制扩容而没有复制堆栈的开销,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs);
- [x] 抢占调度(`不支持windows`):
即使协程进入死循环,它仍能被抢占,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/preemptive.rs);
- [x] Hook:
您可以在协程中自由使用大多数慢系统调用,查看支持的系统调用[unix](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/unix.rs)/[windows](https://github.com/acl-dev/open-coroutine/blob/master/hook/src/syscall/windows.rs);
- [x] 可伸缩栈:
协程栈的大小支持无限制扩容而没有复制堆栈的开销,查看[例子](https://github.com/loongs-zhang/open-coroutine/blob/master/open-coroutine/examples/scalable_stack.rs);
- [x] io_uring(`只支持linux`): 在本地文件IO和网络IO方面支持并兼容io_uring。如果您的系统不支持,它将回退到NIO;
- [x] 优先级: 支持自定义任务优先级,注意协程优先级未对用户开放;
- [x] 任务窃取: 内部使用无锁任务窃取队列;
Expand All @@ -26,7 +29,8 @@
## 🕊 未来计划

- [ ] 完善文档;
- [ ] 增加性能[基准测试](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview);
- [ ]
增加性能[基准测试](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview);
- [ ] 取消协程/任务;
- [ ] 增加性能指标;
- [ ] 增加并发工具包;
Expand Down Expand Up @@ -79,7 +83,7 @@ graph TD
subgraph open-coroutine
end
hook -->|depends on| core
open-coroutine -->|depends on| hook
open-coroutine -->|link| hook
open-coroutine -->|depends on| macros
end
subgraph OperationSystem
Expand Down Expand Up @@ -153,7 +157,7 @@ fn main() {
}
```

### 扩容栈
### 可伸缩栈

```rust
#[open_coroutine::main]
Expand Down Expand Up @@ -183,7 +187,7 @@ fn main() {

[我有故事,你有酒吗?](https://github.com/acl-dev/open-coroutine-docs)

## 🙏 鸣谢
## 👍 鸣谢

这个crate的灵感来自以下项目:

Expand All @@ -193,4 +197,11 @@ fn main() {
- [stacker](https://github.com/rust-lang/stacker)
- [monoio](https://github.com/bytedance/monoio)
- [compio](https://github.com/compio-rs/compio)
- [may](https://github.com/Xudong-Huang/may)
- [may](https://github.com/Xudong-Huang/may)

感谢那些提供帮助的人:

![Amanieu](https://images.weserv.nl/?url=avatars.githubusercontent.com/Amanieu?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![bjorn3](https://images.weserv.nl/?url=avatars.githubusercontent.com/bjorn3?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![workingjubilee](https://images.weserv.nl/?url=avatars.githubusercontent.com/workingjubilee?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
![Noratrieb](https://images.weserv.nl/?url=avatars.githubusercontent.com/Noratrieb?v=4&h=75&w=75&fit=cover&mask=circle&maxage=7d)
3 changes: 2 additions & 1 deletion core/docs/en/coroutine.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ The above is excerpted from [corosensei](https://github.com/Amanieu/corosensei).
| limitations | ✅ Few | ❌ Many |

In general, if the requirements for resource utilization and switching performance are not very strict, using a
stackfull approach would be more convenient and the code would be easier to maintain.
stackfull approach would be more convenient and the code would be easier to maintain. So, `open-coroutine` chooses the
stackfull coroutine.

## State in open-coroutine

Expand Down
16 changes: 12 additions & 4 deletions core/docs/en/overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
## open-coroutine overview
---
title: open-coroutine Overview
date: 2025-01-10 08:24:00
author: loongs-zhang
---

# open-coroutine overview

[![crates.io](https://img.shields.io/crates/v/open-coroutine.svg)](https://crates.io/crates/open-coroutine)
[![docs.rs](https://img.shields.io/badge/docs-release-blue)](https://docs.rs/open-coroutine)
Expand All @@ -8,12 +14,14 @@
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/acl-dev/open-coroutine.svg)](http://isitmaintained.com/project/acl-dev/open-coroutine "Percentage of issues still open")

The `open-coroutine` is a simple, efficient and generic stackfull-coroutine library, you can use this as a performance replacement for IO thread pools.
The `open-coroutine` is a simple, efficient and generic stackfull-coroutine library, you can use this as a performance
replacement for IO thread pools, see [why better](../en/why-better.md).

[//]: # (todo 增加英文版本的文档)

- [Background](../../../docs/cn/background.md)
- [Why rust](../../../docs/cn/why-rust.md)
- [Why better]()
- [Why Rust](../../../docs/cn/why-rust.md)
- [Why Better](../en/why-better.md)
- [Quick Start](../../../README.md)
- [Coroutine Overview](../en/coroutine.md)
- [Scalable Stack Overview](../en/scalable-stack.md)
Expand Down
114 changes: 114 additions & 0 deletions core/docs/en/why-better.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: Why Better
date: 2025-01-10 08:28:00
author: loongs-zhang
---

# Why Better

## Syscall will not block

Firstly, let's take a look at how thread collaborate with syscall.

```mermaid
sequenceDiagram
Actor User Thread
participant Operation System

User Thread ->>+ User Thread: execute
alt User Thread blocked
User Thread ->>+ Operation System: slow syscall
Operation System ->> User Thread: return
end
User Thread ->>+ User Thread: execute
```

If the syscall is a slow syscall, such as `accept` without setting non-blocking, the thread will be blocked for a long
time and unable to do anything until the OS returns. Now, let's take a look at how open-coroutine collaborate with
syscall.

```mermaid
sequenceDiagram
Actor EventLoop Thread
participant Coroutine1
participant Coroutine2
participant Hooked Syscall
participant Operation System

EventLoop Thread ->>+ Coroutine1: schedule
alt Coroutine1 blocked logically
Coroutine1 ->>+ Hooked Syscall: slow syscall
Hooked Syscall ->>+ Operation System: fast syscall
Operation System ->> Hooked Syscall: return errno
Hooked Syscall ->> Coroutine1: suspend the coroutine for a period of time
end
Coroutine1 ->>+ EventLoop Thread: suspended
EventLoop Thread ->>+ Coroutine2: schedule
alt Coroutine2 blocked logically
Coroutine2 ->>+ Hooked Syscall: slow syscall
Hooked Syscall ->>+ Operation System: fast syscall
Operation System ->> Hooked Syscall: return
Hooked Syscall ->> Coroutine2: return
end
Coroutine2 ->>+ EventLoop Thread: return
EventLoop Thread ->>+ Coroutine1: schedule
alt Coroutine1 blocked logically
Coroutine1 ->>+ Hooked Syscall: resume from the last pause
Hooked Syscall ->>+ Operation System: fast syscall
Operation System ->> Hooked Syscall: return
Hooked Syscall ->> Coroutine1: return
end
Coroutine1 ->>+ EventLoop Thread: return
EventLoop Thread ->>+ EventLoop Thread: schedule other coroutines
```

As you can see, `Hooked Syscall` converts `slow syscall` to `fast syscall`. In this way, although the `EventLoop Thread`
will still be blocked when executing syscall, the blocking time is very short. Therefore, compared to the thread model,
`EventLoop Thread` can do more things in the same amount of time.

## Heavy computing will not block

Secondly, let's take a look at how threads handle heavy computations.

```mermaid
sequenceDiagram
Actor User Thread

alt User Thread gets stuck in a loop
User Thread ->>+ User Thread: execute loop
end
```

Just like syscall above, thread will always block in the loop. Then, let's take a look at how open-coroutine handle
heavy computations.

```mermaid
sequenceDiagram
Actor EventLoop Thread
participant Coroutine1
participant Coroutine2
participant Monitor

EventLoop Thread ->>+ Coroutine1: schedule
alt Coroutine1 enters loop
Coroutine1 ->>+ Coroutine1: execute loop for a period of time
Monitor ->> Coroutine1: suspend the coroutine
end
Coroutine1 ->>+ EventLoop Thread: suspended
EventLoop Thread ->>+ Coroutine2: schedule
alt Coroutine2 enters loop
Coroutine2 ->>+ Coroutine2: execute loop for a period of time
Monitor ->> Coroutine1: suspend the coroutine
end
Coroutine2 ->>+ EventLoop Thread: suspended
EventLoop Thread ->>+ Coroutine1: schedule
alt Coroutine1 enters loop
Coroutine1 ->>+ Coroutine1: resume from the last pause
end
Coroutine1 ->>+ EventLoop Thread: return
EventLoop Thread ->>+ EventLoop Thread: schedule other coroutines
```

`Monitor` will monitor the execution of coroutines, and once it found that the execution time of a coroutine is too
long, it will force the coroutine to suspend. So now, we can even use just one `EventLoop Thread` to execute multiple
loops, which cannot be achieved under the single threaded model.