Skip to content
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

2xTx: Refactor to separate Transaction packets from MTU packets #29055

Closed
wants to merge 11 commits into from

Conversation

joncinque
Copy link
Contributor

Problem

As we march towards larger transaction sizes, we want to avoid having a negative impact on the rest of the networking layer. Currently, everything is treated as a general PacketBatch, which is always assumed to have the same size.

For transactions, packets may be larger than 1 MTU, so we need a way to separate transaction packets from all other packets.

Summary of Changes

This is entirely a (pretty big) refactor to make PacketBatch into a generic struct that can accept either a Packet or a TransactionPacket, through a BasePacket trait.

In this PR, both packet types have the same size, so this PR can be merged. Here's what it does in total

  • create BasePacket trait, implemented by Packet and TransactionPacket
  • change PacketBatch to Batch<P: BasePacket>, use everywhere
  • use TransactionPacket for transactions in RPC, banking stage, fetch stage, sigverify, and QUIC

Additional changes required to the refactor:

  • removed the SigVerifier trait, which only had one other totally unused implementation. This made the templating much less messy
  • the CUDA sig verifier used to take in *const Packet, while the underlying libs take uint8_t*, so updated that to *const u8. This worked fine in testing.
  • fetch stage now has two recyclers, one for Packets and one for TransactionPackets. I used the same values to create both of them, but that can be tweaked if needed
  • in banking stage, separated the creation of banking threads to accommodate the different types. No change to functionality
  • create two different TransactionSigVerifiers, one for TransactionPacket (normal tx processing) and one for Packet (vote processing). No change to functionality, just might be confusing

The only potential impact to performance would be going through the trait to get the meta() and meta_mut(), but those should get inlined by the compiler since there's no dynamic dispatch, only templating.

For testing, we can add a simple patch to this that doubles TransactionPacket's size.

For future work, the idea is to update TransactionPacket to have variable size.

Fixes #

@github-actions github-actions bot added explorer Related to the Solana Explorer webapp web3.js Related to the JavaScript client labels Dec 2, 2022
@github-actions github-actions bot removed web3.js Related to the JavaScript client explorer Related to the Solana Explorer webapp labels Dec 2, 2022
Copy link
Contributor

@steviez steviez left a comment

Choose a reason for hiding this comment

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

This looks like a great step in the right direction; still working through some pieces / digesting so will take a more thorough pass in tomorrow

perf/src/perf_libs.rs Outdated Show resolved Hide resolved
sdk/src/packet.rs Outdated Show resolved Hide resolved
KirillLykov
KirillLykov previously approved these changes Dec 5, 2022
Copy link
Contributor

@KirillLykov KirillLykov left a comment

Choose a reason for hiding this comment

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

Looks good to me: despite the size of the changes, 99% of the them are to introduce parametrized types for packets. For the rest, I have only minor comments

sdk/src/packet.rs Show resolved Hide resolved
&bank_forks,
unprocessed_transaction_storage,

if i == 0 || i == 1 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you leave a comment why for 0 and 1 we handle it differently?

Looks like this piece of code requires some refactoring: I think this building logic should be moved to constructor (if it is generic enough) or to some factory function. If you agree, would be nice to leave a comment like TODO(jon): #<issue id> refactor unprocessed_transaction_storage creation in banking stage and you can assign it to me

Copy link
Member

Choose a reason for hiding this comment

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

Please don't add new TODOs into the code 🙏🏼

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to keep the changeset as limited as possible while still doing what was needed. I added a point in the project to address this, and I'll put in a comment explaining what's happening.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't add new TODOs into the code 🙏🏼

sorry, I wrote this before the discussion on discord

sdk/src/packet.rs Outdated Show resolved Hide resolved
@joncinque
Copy link
Contributor Author

Rebased onto #29092

Comment on lines 45 to 47
pub trait BasePacket: Default + Clone + Sync + Send + Eq + fmt::Debug {
const DATA_SIZE: usize;
fn populate_packet<T: Serialize>(&mut self, dest: Option<&SocketAddr>, data: &T) -> Result<()>;
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the benefit of this trait as opposed to using const generics for packet data size and then defining some typedefs for Packet and TransactionPacket?
Something like:

struct GenericPacket<const N: usize> {
    buffer: [u8; N],
    meta: Meta,
}

type Packet = GenericPacket<PACKET_DATA_SIZE>;
type TransactionPacket = GenericPacket<TRANSACTION_DATA_SIZE>;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be honest, I was worried that a second template parameter would make the refactor even longer and more confusing. But it's much better than a macro! Done in ddca0da, thanks for the suggestion!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, now it's actually done, along with the removal of meta() and meta_mut()

@ryoqun
Copy link
Member

ryoqun commented Dec 10, 2022

@joncinque hey, fyi, I'm touching PacketBatch for completely orthogonal functionality addition #29196 than your pr's intention. however, it's conflicting with this pr in purely source code-wise. ;) So, later merge of us will have to fix bunch of merge-conflicts, i guess.

@ryoqun
Copy link
Member

ryoqun commented Dec 10, 2022

btw, completely layman's dumb question: why are we so insisting on arrays? is there justifiable perf observation with realistic mainnet-beta load? I think we can just switch to Vec for now, considering the 2xTx project.

@behzadnouri
Copy link
Contributor

btw, completely layman's dumb question: why are we so insisting on arrays? is there justifiable perf observation with realistic mainnet-beta load? I think we can just switch to Vec for now, considering the 2xTx project.

I would not suggest using Vec. With vectors we would lose any type-safety checks that the buffer is the right size; and that can introduce subtle bugs in so many stages of pipelines.

@joncinque
Copy link
Contributor Author

hey, fyi, I'm touching PacketBatch for completely orthogonal functionality addition #29196 than your pr's intention

@ryoqun ok great, thanks for the heads up! Since you're planning to backport, it probably makes more sense for you to merge first. It doesn't look the change for me will be too bad, but I guess we'll have to see.

KirillLykov
KirillLykov previously approved these changes Dec 14, 2022
Copy link
Contributor

@KirillLykov KirillLykov left a comment

Choose a reason for hiding this comment

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

looks a bit more cumbersome than before but if it since it allows doing static checks, I'm for it

@mergify mergify bot dismissed KirillLykov’s stale review December 19, 2022 17:50

Pull request has been modified.

@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 3, 2023
@mvines
Copy link
Member

mvines commented Jan 3, 2023

@joncinque - this PR got stale 😭

@joncinque joncinque removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 3, 2023
@joncinque
Copy link
Contributor Author

@mvines we're still not sure if this is the right approach, and need to do some testing on it to see. Thanks for flagging that it went stale!

@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 27, 2023
@steviez steviez removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 30, 2023
@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Feb 13, 2023
@github-actions github-actions bot closed this Feb 20, 2023
@mvines
Copy link
Member

mvines commented Feb 20, 2023

sonofa

@joncinque
Copy link
Contributor Author

Merge conflicts on this were monstrous, so I ended up squashing everything and retrying from there. I've almost got a branch ready, which I'll put up in a new PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale [bot only] Added to stale content; results in auto-close after a week.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants