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

feat!: improve serialization efficiency #1467

Closed
wants to merge 1 commit into from

Conversation

wyfo
Copy link
Contributor

@wyfo wyfo commented Sep 20, 2024

Fixed-size objects are now written directly on the writer, instead of being wrapped first into a ZBytes.
Slice like objects are also written on the writer, but obviously prefixed by their size, like ZBytes.

Fixed-size objects are now written directly on the writer,
instead of being wrapped first into a ZBytes.
Slice like objects are also written on the writer,
but obviously prefixed by their size, like ZBytes.
Copy link

PR missing one of the required labels: {'dependencies', 'enhancement', 'new feature', 'bug', 'documentation', 'breaking-change', 'internal'}

}
impl_num!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure implementation for isize/usize makes sense anymore since their sizes are platform dependent (we could always use vle, but the issue is that in some languages they are not independent types and are defined in terms of other integers).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true

@@ -38,7 +38,7 @@ async fn main() {
sample.key_expr().as_str(),
sample
.payload()
.deserialize::<String>()
.try_deserialize::<String>()
Copy link
Member

Choose a reason for hiding this comment

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

Why changing the name? There is already quite a bit of material out there, not mentioning all bindings, that uses deserialize. I don't think this change is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

everything has been changed in the last iteration with @DenisBiryukov91 and @kydos, see the coming PR. This one will be closed.

fn from(t: &Cow<'_, [u8]>) -> Self {
ZSerde.serialize(t)
}
impl SerializedSize for bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we confident that the size of bool will be the same for each platform ?

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 don't thing we care about the size of bool on any platform, if you want to write a compatible serialization, you have to (de)serialize it as a u8, not as an arbitrary integer.

/// assert_eq!(buf.as_slice(), deser.as_slice());
/// ```
///
/// If you want to be sure that no copy is performed at all, then you should use [`ZBytes::slices`].
/// Please note that in this case data may not be contiguous in memory and it is the responsibility of the user to properly parse the raw slices.
pub fn into<'a, T>(&'a self) -> T
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to introduce this API change.
See my previous comment.

ZBytes::new(t)
impl Deserialize<'_> for Vec<u8> {
fn read(_reader: &mut ZBytesReader) -> Result<Self, ZDeserializeError> {
unimplemented!()
Copy link
Member

@Mallets Mallets Sep 20, 2024

Choose a reason for hiding this comment

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

It should be implemented at some point :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No it doesn't, because it should never be called, as the the semantic was:

  • call read if the size is fixed (not the case for Vec<T>)
  • call deserialize/try_from_zbytes if the size is variable

pub trait Deserialize<'a>: Sized + SerializedSize {
fn read(reader: &mut ZBytesReader) -> Result<Self, ZDeserializeError>;
fn deserialize(zbytes: &'a ZBytes) -> Result<Self, ZDeserializeError>;
fn try_from_zbytes(zbytes: ZBytes) -> Result<Self, ZDeserializeError>;
Copy link
Member

Choose a reason for hiding this comment

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

What's the purpose of try_from_zbytes as part of the trait? It seems not needed to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even if everything will be dropped so we don't care anymore, here was the reason:
deserialize couldn't be call in the context of an iterator when you deserialize first a ZBytes, which would then have an anonymous lifetime. So deserializing an iterator of Cow<'a, [u8]> was not possible as 'a would be anonymous in the implementation.
That's why two different methods were needed, one for ZBytes::deserialize, and the other one for the iterator.

@wyfo wyfo closed this Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants