Skip to content

quiche: Add inline variant to ConnectionId#2460

Open
TheJokr wants to merge 4 commits into
cloudflare:masterfrom
TheJokr:lblocher/inline-cid
Open

quiche: Add inline variant to ConnectionId#2460
TheJokr wants to merge 4 commits into
cloudflare:masterfrom
TheJokr:lblocher/inline-cid

Conversation

@TheJokr
Copy link
Copy Markdown
Contributor

@TheJokr TheJokr commented May 5, 2026

I recommend reviewing this PR commit-by-commit.

The existing ConnectionId struct is 24 bytes in size, which is
sufficient to store any QUIC v1 connection ID inline. Taking advantage
of this allows us to avoid allocations when storing and moving CIDs
around throughout quiche and tokio-quiche.

The implementation is heavily inspired by CidOwned in tokio-quiche,
which this new implementation replaces. This includes optimizations to
make hashing and comparisons more efficient by interpreting the entire
inline storage as a u64 array to enable fewer comparisons.

The public API for ConnectionId stays exactly the same, except that ConnectionId::from_vec
can't be const anymore. I had to raise the MSRV to 1.87 to enable the rest
of the functions to stay const.

@TheJokr TheJokr requested a review from a team as a code owner May 5, 2026 13:50
@TheJokr TheJokr force-pushed the lblocher/inline-cid branch from 708d748 to 4e41f20 Compare May 5, 2026 13:51
TheJokr added 4 commits May 6, 2026 11:50
The existing `ConnectionId` struct is 24 bytes in size, which is
sufficient to store any QUIC v1 connection ID inline. Taking advantage
of this allows us to avoid allocations when storing and moving CIDs
around throughout quiche and tokio-quiche.

The implementation is heavily inspired by `CidOwned` in tokio-quiche,
which I will replace in the next commit. This includes optimizations to
make hashing and comparisons more efficient by interpreting the entire
inline storage as a u64 array to enable fewer comparisons.
Now that ConnectionId has inline storage, `cid.to_vec().into()` is a
needlessly inefficient way to clone it.
`ConnectionIdInline` needs Rust 1.87 for const
`slice::split_at_mut_checked` in its `new()` method.
@TheJokr TheJokr force-pushed the lblocher/inline-cid branch from 4e41f20 to 0119ddf Compare May 6, 2026 10:50
@gregor-cf
Copy link
Copy Markdown
Contributor

Nice. I would actually get rid of ConnectionIdInline enum and instead just a SmallVec that stores up to 20 bytes (if we want to support CID of unbounded length). If we just need up to 20bytes, we can just an inline storage.
Having a lifetime on the ConnectionId is a pain in a couple of places.

Comment thread quiche/src/packet.rs
Comment on lines +305 to +308
struct ConnectionIdInline {
storage: [u8; 23],
len: CidInlineLen,
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Using a 23 byte inline array means that ConnectionIdInline can't use niche optimization for enums, so e.g., an Option<ConnectionIdLine> (or ConnectionIdInner) will actually use 32 bytes. Instead, if you limit the inline storage it to 22 bytes, Option should take just 24 bytes. (You'll want to double check with the compiler though :-) )

Copy link
Copy Markdown
Contributor Author

@TheJokr TheJokr May 8, 2026

Choose a reason for hiding this comment

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

Ha, that's why we have CidInlineLen! CidInlineLen provides the niches, which is why ConnectionIdInner is only 24 bytes in total.

The same applies to Option<ConnectionIdInline> and even Option<ConnectionId>.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, yes. It would have helped if I read the all the changes :-)

Instead of the match, you can also use NonZeroU8. And encode it as len + 1. (i.e., non_zero_len==1 represents an actual length of 0). Implication is you can't represent a length of 255. (Or more generally create a NonMaxU8 struct that uses NonZero internally ¯_(ツ)_/¯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants