diff options
author | Aaron O'Mullan <aaron.omullan@gmail.com> | 2022-03-07 11:12:36 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-07 11:12:36 +0100 |
commit | 94c8ecfaaa11906281685fe319ac460758dcd62a (patch) | |
tree | 8dc49b7b6761f708ba7bea61409693fba6e059df | |
parent | f65529aa67664d7ec90b8fb861686aac3ebc4a56 (diff) |
perf(serde_v8): optimize ByteString deserialization (#13853)
-rw-r--r-- | serde_v8/benches/de.rs | 22 | ||||
-rw-r--r-- | serde_v8/benches/ser.rs | 23 | ||||
-rw-r--r-- | serde_v8/src/de.rs | 36 | ||||
-rw-r--r-- | serde_v8/src/error.rs | 1 | ||||
-rw-r--r-- | serde_v8/tests/de.rs | 5 |
5 files changed, 69 insertions, 18 deletions
diff --git a/serde_v8/benches/de.rs b/serde_v8/benches/de.rs index 3b750ac28..23b1161c7 100644 --- a/serde_v8/benches/de.rs +++ b/serde_v8/benches/de.rs @@ -4,6 +4,7 @@ use bencher::{benchmark_group, benchmark_main, Bencher}; use serde::Deserialize; use serde_v8::utils::{js_exec, v8_do}; +use serde_v8::ByteString; #[derive(Debug, Deserialize, PartialEq)] struct MathOp { @@ -135,6 +136,25 @@ fn de_tuple_v8_opt(b: &mut Bencher) { }); } +fn de_bstr_v8_12_b(b: &mut Bencher) { + dedo(r#""hello world\n""#, |scope, v| { + b.iter(move || { + let _: ByteString = serde_v8::from_v8(scope, v).unwrap(); + }); + }); +} + +fn de_bstr_v8_1024_b(b: &mut Bencher) { + dedo( + r#""hello world\n".repeat(1e2).slice(0, 1024)"#, + |scope, v| { + b.iter(move || { + let _: ByteString = serde_v8::from_v8(scope, v).unwrap(); + }); + }, + ); +} + benchmark_group!( benches, de_struct_v8, @@ -152,6 +172,8 @@ benchmark_group!( de_tuple_v8, de_tuple_json, de_tuple_v8_opt, + de_bstr_v8_12_b, + de_bstr_v8_1024_b, ); benchmark_main!(benches); diff --git a/serde_v8/benches/ser.rs b/serde_v8/benches/ser.rs index 8c87be261..3ba95fc2a 100644 --- a/serde_v8/benches/ser.rs +++ b/serde_v8/benches/ser.rs @@ -4,6 +4,7 @@ use bencher::{benchmark_group, benchmark_main, Bencher}; use serde::Serialize; use serde_v8::utils::v8_do; +use serde_v8::ByteString; #[derive(Serialize)] struct MathOp { @@ -87,6 +88,26 @@ fn ser_struct_v8_manual(b: &mut Bencher) { }); } +fn ser_bstr_12_b(b: &mut Bencher) { + serdo(|scope| { + let bstr = ByteString("hello world\n".to_owned().into_bytes()); + b.iter(|| { + let _ = serde_v8::to_v8(scope, &bstr).unwrap(); + }); + }); +} + +fn ser_bstr_1024_b(b: &mut Bencher) { + serdo(|scope| { + let mut s = "hello world\n".repeat(100); + s.truncate(1024); + let bstr = ByteString(s.into_bytes()); + b.iter(|| { + let _ = serde_v8::to_v8(scope, &bstr).unwrap(); + }); + }); +} + benchmark_group!( benches, ser_struct_v8, @@ -102,5 +123,7 @@ benchmark_group!( ser_tuple_v8, ser_tuple_json, ser_struct_v8_manual, + ser_bstr_12_b, + ser_bstr_1024_b, ); benchmark_main!(benches); diff --git a/serde_v8/src/de.rs b/serde_v8/src/de.rs index 2deb5da39..318894c22 100644 --- a/serde_v8/src/de.rs +++ b/serde_v8/src/de.rs @@ -370,25 +370,25 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> // Magic ByteString if name == magic::bytestring::NAME { - if let Some(v8_string) = self.input.to_string(self.scope) { - if v8_string.contains_only_onebyte() { - let mut buffer: Vec<u8> = vec![0u8; v8_string.length()]; - let written = v8_string.write_one_byte( - self.scope, - &mut buffer, - 0, - v8::WriteOptions::NO_NULL_TERMINATION, - ); - assert!(written == v8_string.length()); - return visitor.visit_byte_buf(buffer); - } else { - return Err(Error::Message( - "Expected a valid ByteString.".to_string(), - )); - } - } else { - return Err(Error::ExpectedString); + let v8str = v8::Local::<v8::String>::try_from(self.input) + .map_err(|_| Error::ExpectedString)?; + if !v8str.contains_only_onebyte() { + return Err(Error::ExpectedLatin1); + } + let len = v8str.length(); + let mut buffer = Vec::with_capacity(len); + #[allow(clippy::uninit_vec)] + unsafe { + buffer.set_len(len); } + let written = v8str.write_one_byte( + self.scope, + &mut buffer, + 0, + v8::WriteOptions::NO_NULL_TERMINATION, + ); + assert!(written == len); + return visitor.visit_byte_buf(buffer); } // Regular struct diff --git a/serde_v8/src/error.rs b/serde_v8/src/error.rs index 6f4305536..e4f7f363b 100644 --- a/serde_v8/src/error.rs +++ b/serde_v8/src/error.rs @@ -19,6 +19,7 @@ pub enum Error { ExpectedBuffer, ExpectedUtf8, + ExpectedLatin1, LengthMismatch, } diff --git a/serde_v8/tests/de.rs b/serde_v8/tests/de.rs index 1253ea92b..525089849 100644 --- a/serde_v8/tests/de.rs +++ b/serde_v8/tests/de.rs @@ -3,6 +3,7 @@ use serde::Deserialize; use serde_v8::utils::{js_exec, v8_do}; use serde_v8::Buffer; +use serde_v8::ByteString; use serde_v8::Error; #[derive(Debug, Deserialize, PartialEq)] @@ -311,3 +312,7 @@ detest!( b: "".into() } ); + +detest!(de_bstr, ByteString, "'hello'", ByteString("hello".into())); +defail!(defail_bstr, ByteString, "'👋bye'", |e| e + == Err(Error::ExpectedLatin1)); |