Skip to content

feat: a more lightweight approach #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 69 commits into from
Closed

feat: a more lightweight approach #149

wants to merge 69 commits into from

Conversation

rklaehn
Copy link
Collaborator

@rklaehn rklaehn commented Mar 16, 2025

An attempt to make quic-rpc more lightweight, in support of the blobs 1.0 stabilisation.

API

The old approach tried to provide a high level api for rpc calls. But in our experience with iroh-blobs, gossip, docs etc. in every single case the api was wrapped with some other api anyway. So it seems a lot of the complexity with patterns, to provide said high level api, was not as useful as initially thought.

Efficiency

In memory case

In the old quic-rpc, you would send a pair of mpsc channels, a sender and a receiver, from the client to the server using a mpmc channel. This means that every rpc request, even when the response channel is just an oneshot sender, would have the overhead of 2 mpsc channels. You could reduce this overhead by some sort of complex caching scheme, but the problem remains that you do more that absolutely necessary in many cases.

In the new approach, you manually create an in-memory channel of the appropriate type (oneshot, spsc or none). You can either use the fns in this crate, or even just start with a tokio channel and use the Into conversions into the crate channels.

The result is that the overhead compared to the completely manual case is basically zero, just an enum discriminator. No additional allocations, nothing.

Rpc case

In the old rpc case, each response had to be converted to a large response enum. This does not exist anymore. You still have to serialize the response using postcard and send it, so there is no huge efficiency gain. But at least you get rid of the annoying procedure of defining a response enum.

Boilerplate

Yes, there is more. Every time you do a request, you need to do different things depending on if you are local or remote. For local, you create channels, send one side with the request, and return the other side as usual.

For remote, you write the request to the remote side, get back a pair of send/recv streams, and then return them as a channel of the appropriate kind (or not, in case of channel type none).

This is not that great, but on the plus side it allows you to adjust some details in a straightforward way. E.g. you can set the capacity of local channels and adjust the settings of the send/recv stream for the remote case.

@rklaehn rklaehn changed the title Experiment: a more lightweight approach feat: a more lightweight approach Mar 16, 2025
@n0bot n0bot bot added this to iroh Mar 16, 2025
@github-project-automation github-project-automation bot moved this to 🏗 In progress in iroh Mar 16, 2025
rklaehn added 13 commits March 16, 2025 19:43
…nding on rustc version

E.g.

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: RpcRequests can only be applied to enums
 --> tests/compile_fail/non_enum.rs:4:1
  |
4 | struct Foo;
  | ^^^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: RpcRequests can only be applied to enums
 --> tests/compile_fail/non_enum.rs:4:1
  |
4 | struct Foo;
  | ^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
#[cfg(feature = "rpc")]
#[cfg_attr(quicrpc_docsrs, doc(cfg(feature = "rpc")))]
#[error("error opening stream: {0}")]
Other(#[from] anyhow::Error),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe using an io::Error would match better with the rest of the system?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that iroh currently is using anyhow::Error for connecting.

Connect returns an anyhow::Result, here: https://docs.rs/iroh/latest/iroh/endpoint/struct.Endpoint.html#method.connect

And Endpoint::open_bi also returns an anyhow::Result:
https://docs.rs/iroh/latest/iroh/endpoint/struct.OpenBi.html

I can of course use io::Error::other(theanyhowrerror). Not sure what our plan is there for iroh 1.0. What we don't want here is to put in a concrete iroh error, because then we have the semicircular dependency again.

@rklaehn
Copy link
Collaborator Author

rklaehn commented Apr 1, 2025

NOOOO minimal crates is broken again!!!! What is it this time?

It's such a distraction, just not worth it IMO.

It gives an error in a crate that isn't even in my cargo tree, possibly related to some unstable feature that came and went.
@rklaehn rklaehn requested a review from dignifiedquire April 3, 2025 07:09
we want the raw (iroh-)quinn streams anyway so we can tune them
@rklaehn
Copy link
Collaborator Author

rklaehn commented Apr 3, 2025

Hm, this thing only works with iroh-quinn send and recv streams, and only with iroh or iroh-quinn connections. And I don't intend to change that. So maybe we should publish this under iroh-rpc?

@dignifiedquire
Copy link
Contributor

maybe https://crates.io/crates/irpc, it's still free?

run: |
rm -f Cargo.lock
cargo +nightly check -Z minimal-versions --workspace --all-features --lib --bins
# minimal-crates:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this sucks, but lets bring this back before merging please

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just plain don't know how to fix it. I am getting an error in ahash, which is not even a dependency

cargo +nightly tree --all-features  | grep ahash
<crickets>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed an update that changes CI to this:

cargo +nightly check -Z minimal-versions -p quic-rpc -p quic-rpc-derive --all-features --lib --bins

Error is gone, but I am not super confident that it is doing anything at all anymore...

@rklaehn
Copy link
Collaborator Author

rklaehn commented Apr 3, 2025

Published as https://github.com/n0-computer/irpc

@rklaehn rklaehn closed this Apr 3, 2025
@github-project-automation github-project-automation bot moved this from 🏗 In progress to ✅ Done in iroh Apr 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

2 participants