Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

rlp serialization refactor #4873

Merged
merged 19 commits into from Mar 20, 2017
Merged

rlp serialization refactor #4873

merged 19 commits into from Mar 20, 2017

Conversation

debris
Copy link
Collaborator

@debris debris commented Mar 11, 2017

for now, it's only serialization refactor. it's still WIP, but wanted to know, if you like interface changes I made:

changes:

  • removed BytesEncodable trait
  • removed Encodable trait
  • serialization do not use ToBytes
  • Encodable is no longer implemented to T where T: ToBytes
  • RlpStream does not implement Stream trait. All functions where moved to public interface. I find additional Stream import to be really annoying
  • used byteorder for serialization
  • new api method append_list which should be used to append list of encodable items
  • new api method append_internal which should be used for wrapper types to encoding item without incrementing list elements counter
  • serialization of lists preallocates 1 additional byte for payload. This allows us avoid some unnecessary shifts for short lists

benchmarks:

  • old
test bench_stream_1000_empty_lists   ... bench:       9,839 ns/iter (+/- 1,207)
test bench_stream_nested_empty_lists ... bench:         223 ns/iter (+/- 23)
test bench_stream_u256_value         ... bench:         453 ns/iter (+/- 52)
test bench_stream_u64_value          ... bench:         119 ns/iter (+/- 16)
  • new (update)
test bench_stream_1000_empty_lists   ... bench:       9,143 ns/iter (+/- 1,209)
test bench_stream_nested_empty_lists ... bench:         181 ns/iter (+/- 22)
test bench_stream_u256_value         ... bench:         344 ns/iter (+/- 53)
test bench_stream_u64_value          ... bench:          90 ns/iter (+/- 10)

so encoding integers is almost 25% faster

@debris debris added the A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. label Mar 11, 2017
@debris debris requested a review from rphmeier March 11, 2017 19:05
stream
}

pub fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable {
Copy link
Contributor

Choose a reason for hiding this comment

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

One nice change we could make would be to impl on [u8] instead of &'a [u8] (likewise for str), and then do E: RlpEncodable + ?Sized so we don't have to double-reference slices (which currently leads to lots of &&*my_vec in the codebase)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It will be included in separate pr, this one is big enough ;)

@debris debris added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. and removed A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. labels Mar 12, 2017
@debris debris requested a review from arkpar March 12, 2017 13:15
@debris debris changed the title rlp refactor rlp serialization refactor Mar 12, 2017
@@ -162,7 +162,8 @@ impl Decodable for Step {

impl Encodable for Step {
fn rlp_append(&self, s: &mut RlpStream) {
RlpEncodable::rlp_append(&self.number(), s);
//s.append(&self.number());
Copy link

Choose a reason for hiding this comment

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

Old comment.

@@ -278,6 +279,8 @@ mod tests {
::rlp::encode(&H520::default()).to_vec(),
Vec::new()
];

println!("seal: {:?}", seal);
Copy link

Choose a reason for hiding this comment

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

unnecessary print

finished_list: bool,
}

impl Default for RlpStream {
Copy link
Contributor

Choose a reason for hiding this comment

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

double space after Default

@@ -16,7 +16,7 @@

//! Peer status and capabilities.

use rlp::{DecoderError, RlpDecodable, RlpEncodable, RlpStream, Stream, UntrustedRlp, View};
use rlp::{DecoderError, RlpDecodable, Encodable, RlpStream, UntrustedRlp, View};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why was RlpEncodable renamed, but not the rest?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

RlpDecodable was renamed accordingly in the next pr. The rest of data structures names remained unchanged. I didn't want to introduce to many changes in a single pr

}
}

impl<T> Encodable for Option<T> where T: Encodable {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is dangerous and should be removed IMO. Why does Option has to be a list?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

I know. Might be a good time to get rid of it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will file an issue and fix in the next pr

Copy link
Contributor

Choose a reason for hiding this comment

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

how else would you encode an Option in RLP?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Manually. My point is that changing e.g. a struct member type T to Option<T> silently changes encoding of that member to a list. I recall fixing a bug caused by this.

@arkpar
Copy link
Collaborator

arkpar commented Mar 14, 2017

lgtm

fn rlp_append(&self, s: &mut RlpStream) {
let leading_empty_bytes = self.leading_zeros() as usize / 8;
let mut buffer = [0u8; $size];
(&mut buffer as &mut [u8]).$func::<BigEndian>(*self).expect("buffer.len() == sizeof(*self); qed");
Copy link
Contributor

Choose a reason for hiding this comment

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

can be just
BigEndian::$func(&mut buffer, *self);

let leading_empty_bytes = size.leading_zeros() as usize / 8;
let size_bytes = 4 - leading_empty_bytes as u8;
let mut buffer = [0u8; 4];
(&mut buffer as &mut [u8]).write_u32::<BigEndian>(size).expect("buffer.len() == sizeof(value); qed");
Copy link
Contributor

@NikVolf NikVolf Mar 14, 2017

Choose a reason for hiding this comment

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

can be just
BigEndian::write_u32(&mut buffer, size)

@NikVolf NikVolf added A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. and removed A0-pleasereview 🤓 Pull request needs code review. labels Mar 14, 2017
@gavofyork
Copy link
Contributor

reduction of code size and number of traits is good.

addition of _list everywhere less so.

@debris debris added A0-pleasereview 🤓 Pull request needs code review. and removed A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. labels Mar 14, 2017
@NikVolf
Copy link
Contributor

NikVolf commented Mar 14, 2017

lgtm

@gavofyork
Copy link
Contributor

is it the case that the only underlying reason for the append/append_list API divergence is the need to distinguish between Vec<u8> as a single piece of data and as a list of numbers?

@debris
Copy link
Collaborator Author

debris commented Mar 15, 2017

yes

@gavofyork
Copy link
Contributor

i seem to remember there was something we could do with traits, no? Have a Listable trait which is good for all types except u8?

@debris
Copy link
Collaborator Author

debris commented Mar 17, 2017

i seem to remember there was something we could do with traits, no? Have a Listable trait which is good for all types except u8?

Nothing less complicated than what we had before (with at least 3 different traits) comes to my mind. And I think the solution from this pr is less complicated and error prone

@gavofyork
Copy link
Contributor

well the fact i now have two different functions to call in order to do the same conceptual thing, depending on some arbitrary distinction between datatypes, adds to the complexity.

that said, i won't block it if y'all prefer this way of doing it.

@gavofyork gavofyork added A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. and removed A0-pleasereview 🤓 Pull request needs code review. labels Mar 19, 2017
@debris
Copy link
Collaborator Author

debris commented Mar 20, 2017

thanks, @arkpar @NikVolf @rphmeier @tomusdrw @keorn ?

@NikVolf NikVolf added A8-looksgood 🦄 Pull request is reviewed well. and removed A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. labels Mar 20, 2017
@gavofyork gavofyork merged commit a555686 into master Mar 20, 2017
@gavofyork gavofyork deleted the rlp_cleanup branch March 20, 2017 18:14
@debris debris restored the rlp_cleanup branch July 31, 2017 14:15
@debris debris deleted the rlp_cleanup branch July 31, 2017 14:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A8-looksgood 🦄 Pull request is reviewed well. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants