Closed jbaum98 closed 3 weeks ago
It seems to me that some options are:
futures-channel
.async-oneshot
. hyper compiles using the latest version in git, but not the latest released version.It's pretty easy to implement a oneshot channel with a mutex, especially if there is only one receiver. I'd say just implement it quickly in hyper itself.
The main issue is that hyper usually pulls in h2, which depends on tokio for a lot more than synchronization primitives. So I'm not sure what the practical effect of this would be.
My understanding is that right now, there isn't any http implementation with few dependencies that can be integrated into many executors. Even async_h1
pulls in async-std
. With this change, hyper with http2 disabled would fill that gap.
And, from a quick look, perhaps the goal of dropping tokio as a dependency for h2
also isn't too crazy:
$ rg tokio --glob *.rs --glob '!tests' --glob '!benches' --glob '!examples' --glob '!fuzz' | rg -v '//'
src/proto/go_away.rs:use tokio::io::AsyncWrite;
src/proto/mod.rs:use tokio::io::AsyncWrite;
src/proto/connection.rs:use tokio::io::AsyncRead;
src/proto/ping_pong.rs:use tokio::io::AsyncWrite;
src/proto/streams/streams.rs:use tokio::io::AsyncWrite;
src/proto/streams/send.rs:use tokio::io::AsyncWrite;
src/server.rs:use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
src/client.rs:use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
src/codec/mod.rs:use tokio::io::{AsyncRead, AsyncWrite};
src/codec/mod.rs:use tokio_util::codec::length_delimited;
src/codec/framed_write.rs:use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
src/codec/framed_write.rs:use tokio_util::io::poll_write_buf;
src/codec/framed_read.rs:use tokio::io::AsyncRead;
src/codec/framed_read.rs:use tokio_util::codec::FramedRead as InnerFramedRead;
src/codec/framed_read.rs:use tokio_util::codec::{LengthDelimitedCodec, LengthDelimitedCodecError};
Everything is AsyncRead
, AsyncWrite
, AsyncWriteExt
, ReadBuf
, or tokio_util
.
Agreed. Even just having an HTTP/1 implementation would be nice.
Just a stranger randomly landing on this issue, but you could also consider the oneshot
crate. It has no dependencies, supports async, and is really simple.
Thanks for looking into this.
This would have a pretty huge impact on the transitive dependencies we pull in everywhere hyper is used.
This change likely would not have as big an impact as it appears. hyper only enables the sync
feature of Tokio. That doesn't enable all the dependencies you listed. For example, if you're checking without enabling any of hyper's optional features, this is what an actual compile looks like:
Checking fnv v1.0.7
Checking itoa v1.0.11
Checking bytes v1.7.2
Checking http v1.1.0
Checking pin-project-lite v0.2.14
Checking tokio v1.40.0
Checking http-body v1.0.1
Checking hyper v1.5.0
(Depend on another crate, or vendor)
I'm not likely to be inclined to do that. The implementation in Tokio is very well tested and optimized. Part of keeping hyper safe is vetting its dependencies. I wouldn't want to switch to another dependency that doesn't have the same level of testing, and more importantly, active maintainers able to fix things if a problem is found.
My understanding is that right now, there isn't any http implementation with few dependencies that can be integrated into many executors.
I'd like to clear that up. hyper is indeed a good choice for any runtime. It's been able to support bringing your own runtime for a while, and with hyper v1, we made that even more supported. That it happens to use Tokio for some channels should not affect working with any other runtime. That's because Tokio's sync
implementations don't rely on the runtime module. You can use hyper with any runtime you'd like. :)
This change likely would not have as big an impact as it appears.
Interesting! Clearly cargo tree
's default output didn't mean what I thought. I totally agree that the impact isn't as big as I would have thought. I checked, and it is worth noting that even though only tokio gets compiled, more of its transitive dependencies do get downloaded on a clean build.
Downloaded itoa v1.0.11
Downloaded http-body v1.0.1
Downloaded socket2 v0.5.7
Downloaded tokio-macros v2.4.0
Downloaded unicode-ident v1.0.13
Downloaded proc-macro2 v1.0.88
Downloaded fnv v1.0.7
Downloaded quote v1.0.37
Downloaded pin-project-lite v0.2.14
Downloaded bytes v1.7.2
Downloaded mio v1.0.2
Downloaded http v1.1.0
Downloaded syn v2.0.80
Downloaded tokio v1.40.0
Downloaded libc v0.2.161
Downloaded 15 crates (2.3 MB) in 2.01s
Compiling fnv v1.0.7
Compiling itoa v1.0.11
Compiling bytes v1.7.2
Compiling pin-project-lite v0.2.14
Compiling tokio v1.40.0
Compiling http v1.1.0
Compiling http-body v1.0.1
Compiling hyper v1.5.0 (/home/jake/tmp/hyper)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 13.82s
compared to without tokio:
Downloaded fnv v1.0.7
Downloaded bytes v1.7.2
Downloaded itoa v1.0.11
Downloaded http-body v1.0.1
Downloaded http v1.1.0
Downloaded 5 crates (195.4 KB) in 0.41s
Compiling fnv v1.0.7
Compiling bytes v1.7.2
Compiling itoa v1.0.11
Compiling http v1.1.0
Compiling http-body v1.0.1
Compiling hyper v1.5.0 (/home/jake/tmp/hyper)
So I think dropping the tokio dependency makes a small difference, but definitely it's not dramatic as I thought.
I'm not likely to be inclined to do that. The implementation in Tokio is very well tested and optimized.
That makes sense. Would you be open to a PR that pulled out the tokio implementation? I'd understand if in your judgement it's not worth it.
I'd like to clear that up. hyper is indeed a good choice for any runtime.
Heard! Thank you for the work that went into making that the case! Seeing the dependency on tokio is kind of a red flag, but clearly that doesn't have the impact on compile-time or on run-time that one might expect from "pulling in a whole 'nother executor".
can we also drop the `Send + 'static' requirement if we were to drop tokio dependency to support thread per core runtimes better.
thread per core runtimes
Just to clarify, most all runtimes are thread per core, in that they create one thread per core of the machine (Tokio does this). A clearer term is shared-nothing.
can we also drop the `Send + 'static' requirement if we were to drop tokio dependency
That's not coming from Tokio being used. hyper happens to use a synchronization type from Tokio, but that does not affect hyper::rt
at all. Additionally, there isn't much of a Send
requirement. We keep an example that compiles in CI to make sure you can use hyper on shared-nothing executors: https://github.com/hyperium/hyper/blob/master/examples/single_threaded.rs
Now that hyper uses its own traits instead of tokios (#3110, #3230), the only place that tokio is used is to provide
tokio::sync::oneshot::Receiver
insrc/upgarde.rs
. If we could find a way to implement this functionality without tokio's oneshot, we could drop the dependency entirely. This would have a pretty huge impact on the transitive dependencies we pull in everywhere hyper is used: from this:to this:
I also think this would make hyper more appealing to use with other executors like
smol
@notgull.