It seems that many of the adapters in futures::stream::StreamExt
require an async closure regardless of whether or not there is anything to await
on.
Is an async closure, without anything to await on, more expensive than a regular closure?
It seems that many of the adapters in futures::stream::StreamExt
require an async closure regardless of whether or not there is anything to await
on.
Is an async closure, without anything to await on, more expensive than a regular closure?
It depends. There might be an extra copy of some data that you could otherwise avoid, but they would be very close.
Note that tokio::stream::StreamExt
have versions of several of the combinators without them being async.
In debug mode, definitely - there are more types. But in release mode, it's likely that it'll be all optimized out. You can also use std::future::ready
which stabilizes in 8 days or futures::future::ready
until then to shorten your code and avoid some difficult borrowing errors that occur with async blocks.
Regarding the non-async combinators, perhaps I am missing something here. The only two functions in StreamExt
trait that I can see that take closures and that don't return futures are map
and inspect
. The others have some variant of the trait bound F: FnMut(..) -> Fut
which (I think) means I have to wrap my non-async code in an async block.
For example, assume msg
was a Result whose error variant can be safely ignored. I think (correct me if I am wrong) I have to write:
let messages = stream
.filter_map(|msg| async {
msg.ok()
}).collect::<Vec<String>>().await;
Instead of something like:
let messages = stream
.filter_map(Result::ok)
.collect::<Vec<String>>().await;
I'm referring to Tokio's StreamExt
. Tokio has its own StreamExt
, distinct from futures' StreamExt
.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.