Update SszEncoder
This commit is contained in:
parent
aeb17c73f6
commit
480c5ff160
@ -4,6 +4,15 @@ extern crate criterion;
|
|||||||
use criterion::black_box;
|
use criterion::black_box;
|
||||||
use criterion::{Benchmark, Criterion};
|
use criterion::{Benchmark, Criterion};
|
||||||
use ssz::{Decodable, Encodable};
|
use ssz::{Decodable, Encodable};
|
||||||
|
use ssz_derive::{Decode, Encode};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Encode, Decode)]
|
||||||
|
pub struct FixedLen {
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
c: u64,
|
||||||
|
d: u64,
|
||||||
|
}
|
||||||
|
|
||||||
fn criterion_benchmark(c: &mut Criterion) {
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
let n = 8196;
|
let n = 8196;
|
||||||
@ -32,6 +41,39 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
})
|
})
|
||||||
.sample_size(100),
|
.sample_size(100),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let fixed_len = FixedLen {
|
||||||
|
a: 42,
|
||||||
|
b: 42,
|
||||||
|
c: 42,
|
||||||
|
d: 42,
|
||||||
|
};
|
||||||
|
let fixed_len_vec: Vec<FixedLen> = vec![fixed_len; 8196];
|
||||||
|
|
||||||
|
let vec = fixed_len_vec.clone();
|
||||||
|
c.bench(
|
||||||
|
&format!("vec_of_{}_struct", n),
|
||||||
|
Benchmark::new("as_ssz_bytes", move |b| {
|
||||||
|
b.iter_with_setup(|| vec.clone(), |vec| black_box(vec.as_ssz_bytes()))
|
||||||
|
})
|
||||||
|
.sample_size(100),
|
||||||
|
);
|
||||||
|
|
||||||
|
let vec = fixed_len_vec.clone();
|
||||||
|
let bytes = vec.as_ssz_bytes();
|
||||||
|
c.bench(
|
||||||
|
&format!("vec_of_{}_struct", n),
|
||||||
|
Benchmark::new("from_ssz_bytes", move |b| {
|
||||||
|
b.iter_with_setup(
|
||||||
|
|| bytes.clone(),
|
||||||
|
|bytes| {
|
||||||
|
let vec: Vec<u64> = Vec::from_ssz_bytes(&bytes).unwrap();
|
||||||
|
black_box(vec)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.sample_size(100),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(benches, criterion_benchmark);
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
32
eth2/utils/ssz/examples/large_list_of_structs.rs
Normal file
32
eth2/utils/ssz/examples/large_list_of_structs.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//! Encode and decode a list many times.
|
||||||
|
//!
|
||||||
|
//! Useful for `cargo flamegraph`.
|
||||||
|
|
||||||
|
use ssz::{Decodable, Encodable};
|
||||||
|
use ssz_derive::{Decode, Encode};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Encode, Decode)]
|
||||||
|
pub struct FixedLen {
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
c: u64,
|
||||||
|
d: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let fixed_len = FixedLen {
|
||||||
|
a: 42,
|
||||||
|
b: 42,
|
||||||
|
c: 42,
|
||||||
|
d: 42,
|
||||||
|
};
|
||||||
|
|
||||||
|
let vec: Vec<FixedLen> = vec![fixed_len; 8196];
|
||||||
|
|
||||||
|
let output: Vec<Vec<u64>> = (0..40_000)
|
||||||
|
.into_iter()
|
||||||
|
.map(|_| Vec::from_ssz_bytes(&vec.as_ssz_bytes()).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
println!("{}", output.len());
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use ssz::{Decodable, DecodeError, Encodable, SszDecoderBuilder, SszEncoder, SszStream};
|
use ssz::{Decodable, DecodeError, Encodable, SszDecoderBuilder, SszEncoder};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Foo {
|
pub struct Foo {
|
||||||
@ -23,7 +23,7 @@ impl Encodable for Foo {
|
|||||||
encoder.append(&self.b);
|
encoder.append(&self.b);
|
||||||
encoder.append(&self.c);
|
encoder.append(&self.c);
|
||||||
|
|
||||||
buf.append(&mut encoder.drain());
|
encoder.drain_onto(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,10 +32,14 @@ pub struct SszEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SszEncoder {
|
impl SszEncoder {
|
||||||
|
pub fn list(num_fixed_bytes: usize) -> Self {
|
||||||
|
Self::container(num_fixed_bytes)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn container(num_fixed_bytes: usize) -> Self {
|
pub fn container(num_fixed_bytes: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
offset: num_fixed_bytes,
|
offset: num_fixed_bytes,
|
||||||
fixed_bytes: vec![],
|
fixed_bytes: Vec::with_capacity(num_fixed_bytes),
|
||||||
variable_bytes: vec![],
|
variable_bytes: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,10 +55,9 @@ impl SszEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drain(mut self) -> Vec<u8> {
|
pub fn drain_onto(mut self, buf: &mut Vec<u8>) {
|
||||||
self.fixed_bytes.append(&mut self.variable_bytes);
|
buf.append(&mut self.fixed_bytes);
|
||||||
|
buf.append(&mut self.variable_bytes);
|
||||||
self.fixed_bytes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +66,7 @@ pub struct VariableLengths {
|
|||||||
pub variable_bytes_length: usize,
|
pub variable_bytes_length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Provides a buffer for appending SSZ values.
|
/// Provides a buffer for appending SSZ values.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SszStream {
|
pub struct SszStream {
|
||||||
@ -152,6 +156,7 @@ impl SszStream {
|
|||||||
self.fixed_bytes
|
self.fixed_bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Encode `len` as a little-endian byte vec of `BYTES_PER_LENGTH_OFFSET` length.
|
/// Encode `len` as a little-endian byte vec of `BYTES_PER_LENGTH_OFFSET` length.
|
||||||
///
|
///
|
||||||
|
@ -31,7 +31,6 @@ impl<T: Encodable> Encodable for Vec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
|
|
||||||
if T::is_ssz_fixed_len() {
|
if T::is_ssz_fixed_len() {
|
||||||
buf.reserve(T::ssz_fixed_len() * self.len());
|
buf.reserve(T::ssz_fixed_len() * self.len());
|
||||||
|
|
||||||
@ -39,28 +38,13 @@ impl<T: Encodable> Encodable for Vec<T> {
|
|||||||
item.ssz_append(buf);
|
item.ssz_append(buf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
let mut encoder = SszEncoder::list(self.len() * BYTES_PER_LENGTH_OFFSET);
|
||||||
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 fixed = Vec::with_capacity(offset);
|
|
||||||
let mut variable = vec![];
|
|
||||||
|
|
||||||
for item in self {
|
for item in self {
|
||||||
fixed.append(&mut encode_length(offset));
|
encoder.append(item);
|
||||||
let mut bytes = item.as_ssz_bytes();
|
|
||||||
offset += bytes.len();
|
|
||||||
variable.append(&mut bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append(&mut fixed);
|
encoder.drain_onto(buf);
|
||||||
buf.append(&mut variable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,21 +17,19 @@ mod decode;
|
|||||||
mod encode;
|
mod encode;
|
||||||
|
|
||||||
pub use decode::{Decodable, DecodeError, SszDecoderBuilder};
|
pub use decode::{Decodable, DecodeError, SszDecoderBuilder};
|
||||||
pub use encode::{Encodable, SszEncoder, SszStream};
|
pub use encode::{Encodable, SszEncoder};
|
||||||
|
|
||||||
pub const BYTES_PER_LENGTH_OFFSET: usize = 4;
|
pub const BYTES_PER_LENGTH_OFFSET: usize = 4;
|
||||||
pub const MAX_LENGTH_VALUE: usize = 1 << (BYTES_PER_LENGTH_OFFSET * 8) - 1;
|
pub const MAX_LENGTH_VALUE: usize = 1 << (BYTES_PER_LENGTH_OFFSET * 8) - 1;
|
||||||
|
|
||||||
/// Convenience function to SSZ encode an object supporting ssz::Encode.
|
/// Convenience function to SSZ encode an object supporting ssz::Encode.
|
||||||
|
///
|
||||||
|
/// Equivalent to `val.as_ssz_bytes()`.
|
||||||
pub fn ssz_encode<T>(val: &T) -> Vec<u8>
|
pub fn ssz_encode<T>(val: &T) -> Vec<u8>
|
||||||
where
|
where
|
||||||
T: Encodable,
|
T: Encodable,
|
||||||
{
|
{
|
||||||
let mut buf = vec![];
|
val.as_ssz_bytes()
|
||||||
|
|
||||||
val.ssz_append(&mut buf);
|
|
||||||
|
|
||||||
buf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![recursion_limit="128"]
|
#![recursion_limit = "128"]
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
|
|||||||
let field_idents = get_serializable_named_field_idents(&struct_data);
|
let field_idents = get_serializable_named_field_idents(&struct_data);
|
||||||
let field_types_a = get_serializable_field_types(&struct_data);
|
let field_types_a = get_serializable_field_types(&struct_data);
|
||||||
let field_types_b = field_types_a.clone();
|
let field_types_b = field_types_a.clone();
|
||||||
|
let field_types_c = field_types_a.clone();
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl ssz::Encodable for #name {
|
impl ssz::Encodable for #name {
|
||||||
@ -102,14 +103,19 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ssz_bytes(&self) -> Vec<u8> {
|
fn ssz_append(&self, buf: &mut Vec<u8>) {
|
||||||
let mut stream = ssz::SszStream::new();
|
let offset = #(
|
||||||
|
<#field_types_c as ssz::Encodable>::ssz_fixed_len() +
|
||||||
|
)*
|
||||||
|
0;
|
||||||
|
|
||||||
|
let mut encoder = ssz::SszEncoder::container(offset);
|
||||||
|
|
||||||
#(
|
#(
|
||||||
stream.append(&self.#field_idents);
|
encoder.append(&self.#field_idents);
|
||||||
)*
|
)*
|
||||||
|
|
||||||
stream.drain()
|
encoder.drain_onto(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user