Skip to content

Commit c758af5

Browse files
committed
Add TaskSeq vs AsyncSeq comparison table
1 parent 08d8e99 commit c758af5

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

README.md

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@ Latest version [can be installed from Nuget][nuget].
2424
- [`taskSeq` computation expressions](#taskseq-computation-expressions)
2525
- [Installation](#installation)
2626
- [Examples](#examples)
27-
- [Status & planning](#status--planning)
27+
- [Choosing between `AsyncSeq` and `TaskSeq`](#choosing-between-asyncseq-and-taskseq)
28+
- [Status \& planning](#status--planning)
2829
- [Implementation progress](#implementation-progress)
2930
- [Progress `taskSeq` CE](#progress-taskseq-ce)
3031
- [Progress and implemented `TaskSeq` module functions](#progress-and-implemented-taskseq-module-functions)
3132
- [More information](#more-information)
32-
- [Further reading `IAsyncEnumerable`](#further-reading-iasyncenumerable)
33+
- [Further reading on `IAsyncEnumerable`](#further-reading-on-iasyncenumerable)
3334
- [Further reading on resumable state machines](#further-reading-on-resumable-state-machines)
3435
- [Further reading on computation expressions](#further-reading-on-computation-expressions)
35-
- [Building & testing](#building--testing)
36+
- [Building \& testing](#building--testing)
3637
- [Prerequisites](#prerequisites)
3738
- [Build the solution](#build-the-solution)
3839
- [Run the tests](#run-the-tests)
@@ -163,6 +164,33 @@ let feedFromTwitter user pwd = taskSeq {
163164
}
164165
```
165166

167+
## Choosing between `AsyncSeq` and `TaskSeq`
168+
169+
The [`AsyncSeq`][11] and `TaskSeq` library both operate on asynchronous sequences, but there are a few fundamental differences, most notably that the former _does not_ implement `IAsyncEnumerable<'T>`, but has its own same-named, but differently behaving type. Another core difference is that `TaskSeq` uses `ValueTasks` for the asynchronous computations, and `AsyncSeq` uses F#'s `Async<'T>`.
170+
171+
There are more differences:
172+
173+
| | `TaskSeq` | `AsyncSeq` |
174+
|------------------------|---------------------------------------------------------------------------------------|----------------------------------------------------------------------|
175+
| **Frameworks** | .NET 5.0+, NetStandard 2.1 | .NET 5.0+, NetStandard 2.0 and 2.1, .NET Framework 4.6.1+ |
176+
| **Underlying type** | `System.Collections.Generic.IAsyncEnumerable<'T> | Its own type, also called `IAsyncEnumerable<'T>`, but not compatible |
177+
| **Implementation** | State machine (statically compiled) | No state machine, continuation style |
178+
| **Semantics** | `seq`-like: on-demand | `seq`-like: on-demand |
179+
| **Support `let!`** | All `task`-like: `Async<'T>`, `ValueTask<'T>` and `ValueTask`, `Task<'T>` and `Task` or anything with `GetAwaiter()` | `Async<'T>` only |
180+
| **Support `do!`** | `Async<unit>`, `Task<unit>` and `Task`, `ValueTask<unit>` and `ValueTask` | `Async<unit>` only |
181+
| **Support `yield!`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq` |
182+
| **Support `for`** | `IAsyncEnumerable<'T>`, `AsyncSeq`, any sequence | `AsyncSeq` any sequence |
183+
| **Behavior with `yield`** | Zero allocations, no `Task` or even `ValueTask` created | Allocated, an F# `Async` wrapped in a singleton `AsyncSeq` |
184+
| **Conversion to other** | `TaskSeq.toAsyncSeq` | `AsyncSeq.toAsyncEnum` |
185+
| **Conversion from other** | Implicit (yield!) or `TaskSeq.ofAsyncSeq` | `AsyncSeq.ofAsyncEnum` |
186+
| **Recursion in `yield!`** | No (requires F# support, upcoming) | Yes |
187+
| **Based on F# concept of** | `task` | `async` |
188+
| **MoveNext operation** | `ValueTask<bool>` | `Async<'T option>` |
189+
| **Current operation** | `ValueOption<'T>` | `Option<'T>` |
190+
| **Cancellation** | Implicit token governing iteration | Implicit token passed to each subtask |
191+
| **Performance** | Very high, negligible allocations | Slower, more allocations, due to using `async` |
192+
| **Parallelism** | Possible with ChildTask, support will follow | Supported explicitly |
193+
166194
## Status & planning
167195

168196
This project has stable features currently, but before we go full "version one", we'd like to complete the surface area. This section covers the status of that, with a full list of implmented functions below. Here's the short list:
@@ -330,12 +358,6 @@ The following is the progress report:
330358

331359
## More information
332360

333-
### The AsyncSeq library
334-
335-
If you're looking to use `IAsyncEnumerable` with `async` and not `task`, the existing [`AsyncSeq`][11] library already provides excellent coverage of that use case. While `TaskSeq` is intended to interoperate with `async` as `task` does, it's not intended to provide an `AsyncSeq` type (at least not yet).
336-
337-
In short, if your application is using `Async` (and the parallelism features stemming from that), consider using the `AsyncSeq` library instead.
338-
339361
### Further reading on `IAsyncEnumerable`
340362

341363
- A good C#-based introduction [can be found in this blog][8].

0 commit comments

Comments
 (0)