summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@gmail.com>2022-03-07 11:12:36 +0100
committerGitHub <noreply@github.com>2022-03-07 11:12:36 +0100
commit94c8ecfaaa11906281685fe319ac460758dcd62a (patch)
tree8dc49b7b6761f708ba7bea61409693fba6e059df
parentf65529aa67664d7ec90b8fb861686aac3ebc4a56 (diff)
perf(serde_v8): optimize ByteString deserialization (#13853)
-rw-r--r--serde_v8/benches/de.rs22
-rw-r--r--serde_v8/benches/ser.rs23
-rw-r--r--serde_v8/src/de.rs36
-rw-r--r--serde_v8/src/error.rs1
-rw-r--r--serde_v8/tests/de.rs5
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));