Begin refactor for less allocation
This commit is contained in:
parent
acf854f558
commit
daf6912d18
@ -1,4 +1,4 @@
|
|||||||
//! Encode and decode a list 10,000 times.
|
//! Encode and decode a list many times.
|
||||||
//!
|
//!
|
||||||
//! Useful for `cargo flamegraph`.
|
//! Useful for `cargo flamegraph`.
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ use ssz::{Decodable, Encodable};
|
|||||||
fn main() {
|
fn main() {
|
||||||
let vec: Vec<u64> = vec![4242; 8196];
|
let vec: Vec<u64> = vec![4242; 8196];
|
||||||
|
|
||||||
let output: Vec<Vec<u64>> = (0..10_000)
|
let output: Vec<Vec<u64>> = (0..40_000)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|_| Vec::from_ssz_bytes(&vec.as_ssz_bytes()).unwrap())
|
.map(|_| Vec::from_ssz_bytes(&vec.as_ssz_bytes()).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use ssz::{Decodable, DecodeError, Encodable, SszDecoderBuilder, SszStream};
|
use ssz::{encode_length, Decodable, DecodeError, Encodable, SszDecoderBuilder, SszStream};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Foo {
|
pub struct Foo {
|
||||||
@ -12,14 +12,23 @@ impl Encodable for Foo {
|
|||||||
<u16 as Encodable>::is_ssz_fixed_len() && <Vec<u16> as Encodable>::is_ssz_fixed_len()
|
<u16 as Encodable>::is_ssz_fixed_len() && <Vec<u16> as Encodable>::is_ssz_fixed_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
let mut stream = SszStream::new();
|
let offset = <u16 as Encodable>::ssz_fixed_len()
|
||||||
|
+ <Vec<u16> as Encodable>::ssz_fixed_len()
|
||||||
|
+ <u16 as Encodable>::ssz_fixed_len();
|
||||||
|
|
||||||
stream.append(&self.a);
|
let mut fixed = Vec::with_capacity(offset);
|
||||||
stream.append(&self.b);
|
let mut variable = vec![];
|
||||||
stream.append(&self.c);
|
|
||||||
|
|
||||||
stream.drain()
|
if <u16 as Encodable>::is_ssz_fixed_len() {
|
||||||
|
self.a.ssz_append(&mut fixed);
|
||||||
|
} else {
|
||||||
|
fixed.append(encode_length())
|
||||||
|
}
|
||||||
|
|
||||||
|
if <Vec<u16> as Encodable>::is_ssz_fixed_len() {
|
||||||
|
self.a.ssz_append(&mut fixed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ use super::*;
|
|||||||
mod impls;
|
mod impls;
|
||||||
|
|
||||||
pub trait Encodable {
|
pub trait Encodable {
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8>;
|
|
||||||
|
|
||||||
fn is_ssz_fixed_len() -> bool;
|
fn is_ssz_fixed_len() -> bool;
|
||||||
|
|
||||||
|
fn ssz_append(&self, buf: &mut Vec<u8>);
|
||||||
|
|
||||||
/// The number of bytes this object occupies in the fixed-length portion of the SSZ bytes.
|
/// The number of bytes this object occupies in the fixed-length portion of the SSZ bytes.
|
||||||
///
|
///
|
||||||
/// By default, this is set to `BYTES_PER_LENGTH_OFFSET` which is suitable for variable length
|
/// By default, this is set to `BYTES_PER_LENGTH_OFFSET` which is suitable for variable length
|
||||||
@ -15,6 +15,14 @@ pub trait Encodable {
|
|||||||
fn ssz_fixed_len() -> usize {
|
fn ssz_fixed_len() -> usize {
|
||||||
BYTES_PER_LENGTH_OFFSET
|
BYTES_PER_LENGTH_OFFSET
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_ssz_bytes(&self) -> Vec<u8> {
|
||||||
|
let mut buf = vec![];
|
||||||
|
|
||||||
|
self.ssz_append(&mut buf);
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VariableLengths {
|
pub struct VariableLengths {
|
||||||
@ -40,11 +48,13 @@ impl SszStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Append some item to the stream.
|
/// Append some item to the stream.
|
||||||
pub fn append<T: Encodable>(&mut self, item: &T) {
|
pub fn append<T: Encodable>(&mut self, item: &T) {
|
||||||
let mut bytes = item.as_ssz_bytes();
|
let mut bytes = item.as_ssz_bytes();
|
||||||
|
|
||||||
if T::is_ssz_fixed_len() {
|
if T::is_ssz_fixed_len() {
|
||||||
|
self.app
|
||||||
self.fixed_bytes.append(&mut bytes);
|
self.fixed_bytes.append(&mut bytes);
|
||||||
} else {
|
} else {
|
||||||
self.variable_lengths.push(VariableLengths {
|
self.variable_lengths.push(VariableLengths {
|
||||||
@ -57,6 +67,32 @@ impl SszStream {
|
|||||||
self.variable_bytes.append(&mut bytes);
|
self.variable_bytes.append(&mut bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
pub fn reserve<T: Encodable>(&mut self, additional: usize) {
|
||||||
|
if T::is_ssz_fixed_len() {
|
||||||
|
self.fixed_bytes.reserve(additional * T::ssz_fixed_len());
|
||||||
|
} else {
|
||||||
|
self.fixed_bytes
|
||||||
|
.reserve(additional * BYTES_PER_LENGTH_OFFSET);
|
||||||
|
self.variable_lengths.reserve(additional);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_fixed_bytes(&mut self, bytes: &[u8]) {
|
||||||
|
self.fixed_bytes.extend_from_slice(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_variable_bytes(&mut self, bytes: &[u8]) {
|
||||||
|
self.variable_lengths.push(VariableLengths {
|
||||||
|
fixed_bytes_position: self.fixed_bytes.len(),
|
||||||
|
variable_bytes_length: bytes.len(),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.fixed_bytes
|
||||||
|
.append(&mut vec![0; BYTES_PER_LENGTH_OFFSET]);
|
||||||
|
|
||||||
|
self.variable_bytes.extend_from_slice(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the offsets (if any) in the fixed-length bytes to correctly point to the values in
|
/// Update the offsets (if any) in the fixed-length bytes to correctly point to the values in
|
||||||
/// the variable length part.
|
/// the variable length part.
|
||||||
|
@ -12,8 +12,8 @@ macro_rules! impl_encodable_for_uint {
|
|||||||
$bit_size / 8
|
$bit_size / 8
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
self.to_le_bytes().to_vec()
|
buf.extend_from_slice(&self.to_le_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -30,16 +30,24 @@ impl<T: Encodable> Encodable for Vec<T> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
|
|
||||||
if T::is_ssz_fixed_len() {
|
if T::is_ssz_fixed_len() {
|
||||||
let mut bytes = Vec::with_capacity(T::ssz_fixed_len() * self.len());
|
buf.reserve(T::ssz_fixed_len() * self.len());
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
bytes.append(&mut item.as_ssz_bytes());
|
item.ssz_append(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes
|
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
for item in self {
|
||||||
|
let mut substream = SszStream::new();
|
||||||
|
|
||||||
|
item.ssz_append(&mut substream);
|
||||||
|
|
||||||
|
s.append_variable_bytes(&substream.drain());
|
||||||
|
}
|
||||||
|
*/
|
||||||
let mut offset = self.len() * BYTES_PER_LENGTH_OFFSET;
|
let mut offset = self.len() * BYTES_PER_LENGTH_OFFSET;
|
||||||
let mut fixed = Vec::with_capacity(offset);
|
let mut fixed = Vec::with_capacity(offset);
|
||||||
let mut variable = vec![];
|
let mut variable = vec![];
|
||||||
@ -51,9 +59,8 @@ impl<T: Encodable> Encodable for Vec<T> {
|
|||||||
variable.append(&mut bytes);
|
variable.append(&mut bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed.append(&mut variable);
|
buf.append(&mut fixed);
|
||||||
|
buf.append(&mut variable);
|
||||||
fixed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,8 +71,8 @@ impl Encodable for bool {
|
|||||||
Some(8)
|
Some(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn ssz_append(&self, s: &mut SszStream) {
|
||||||
(*self as u8).to_le_bytes().to_vec()
|
s.append_fixed_bytes(&(self as u8).to_le_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,48 +101,6 @@ macro_rules! impl_encodable_for_u8_array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl_encodable_for_u8_array!(4);
|
impl_encodable_for_u8_array!(4);
|
||||||
|
|
||||||
macro_rules! impl_encodable_for_u8_array {
|
|
||||||
($len: expr) => {
|
|
||||||
impl Encodable for [u8; $len] {
|
|
||||||
|
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
|
||||||
let bytes: Vec<u8> = self.iter().cloned().collect();
|
|
||||||
s.append_encoded_raw(&bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_encodable_for_u8_array!(4);
|
|
||||||
|
|
||||||
impl Encodable for bool {
|
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
|
||||||
let byte = if *self { 0b0000_0001 } else { 0b0000_0000 };
|
|
||||||
s.append_encoded_raw(&[byte]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encodable for H256 {
|
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
|
||||||
s.append_encoded_raw(self.as_bytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encodable for Address {
|
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
|
||||||
s.append_encoded_raw(self.as_bytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Encodable for Vec<T>
|
|
||||||
where
|
|
||||||
T: Encodable,
|
|
||||||
{
|
|
||||||
fn ssz_append(&self, s: &mut SszStream) {
|
|
||||||
s.append_vec(&self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -27,9 +27,11 @@ pub fn ssz_encode<T>(val: &T) -> Vec<u8>
|
|||||||
where
|
where
|
||||||
T: Encodable,
|
T: Encodable,
|
||||||
{
|
{
|
||||||
let mut ssz_stream = SszStream::new();
|
let mut buf = vec![];
|
||||||
ssz_stream.append(val);
|
|
||||||
ssz_stream.drain()
|
val.ssz_append(&mut buf);
|
||||||
|
|
||||||
|
buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use ssz::{Decodable, Encodable};
|
use ssz::{Decodable, Encodable};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
|
|
||||||
|
/*
|
||||||
fn round_trip<T: Encodable + Decodable + std::fmt::Debug + PartialEq>(items: Vec<T>) {
|
fn round_trip<T: Encodable + Decodable + std::fmt::Debug + PartialEq>(items: Vec<T>) {
|
||||||
for item in items {
|
for item in items {
|
||||||
let encoded = &item.as_ssz_bytes();
|
let encoded = &item.as_ssz_bytes();
|
||||||
@ -157,3 +158,4 @@ fn vec_of_variable_len_struct() {
|
|||||||
|
|
||||||
round_trip(items);
|
round_trip(items);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user