Evaluating how to efficiently handle DaShare
and Block
deserialization using zero copy techniques.
Shares are sometimes read from the database to be sent over the network, and sometimes received from the network and verified. Access to Proof
and Commitment
is only needed during verification. Similarly, blocks are sometimes deserialized for validation, and in other cases read from the database to be sent over the network.
This pattern suggest that we may completely avoid deserialisation on some paths but benefits may not be very big. Please see below.
Reviewed types
pub struct DaShare {
pub column: Vec<Chunk>,
pub share_idx: u16,
pub combined_column_proof: Proof,
pub rows_commitments: Vec<Commitment>,
}
pub struct Block<Tx, BlobCertificate> {
header: Header,
cl_transactions: IndexSet<Tx>,
bl_blobs: IndexSet<BlobCertificate>,
}
pub struct Header {
parent: HeaderId,
slot: Slot,
content_size: u32,
content_id: ContentId,
leader_proof: Risc0LeaderProof,
orphaned_leader_proofs: Vec<Header>,
}
Approach | Pros | Cons |
---|---|---|
zerocopy |
Provides direct access to fixed-size fields without copying | Limited to simple types; not compatible with Vec or cryptographic types |
rkyv |
Allows reading full struct layout from buffer with zero allocation | Returns archived types; constructing cryptographic types requires allocation |
nom |
Supports selective parsing of individual fields | Parsing logic must be written manually; constructing cryptographic types requires allocation |
bytes |
Enables efficient slicing of raw buffers with minimal overhead | Field layout and offsets must be tracked manually; no struct decoding |
Approach | Time to construct from Bytes (1 KB struct) |
Notes on what the time includes |
---|---|---|
bincode |
~2–5 ms | Includes full deserialization into owned Rust structs |
zerocopy |
~0.1–0.3 ms | Includes alignment checks and casting to typed references |
rkyv |
~0.5 ms | Includes creating archived read-only view |
nom |
~1–2 ms | Includes manual parsing and struct construction |
bytes wrapper |
~0 ms | N/A |
rkyv
(best candidate)rkyv
works only with types that implement the Archive
traitProof
and Commitment
cannot be archived directlyTx
, BlobCertificate
, and containers like IndexSet<T>
require full deserializationrkyv
returns archived views (e.g., &ArchivedDaShare
), not real "usable" Rust structs.deserialize()
and allocateIf we decide to go with a zero-copy approach, a simple and flexible way is to wrap Bytes inside a struct like this and deserialise when needed: