mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
perf(serde_v8): optimize ByteString deserialization (#13853)
This commit is contained in:
parent
f65529aa67
commit
94c8ecfaaa
5 changed files with 69 additions and 18 deletions
|
@ -4,6 +4,7 @@ use bencher::{benchmark_group, benchmark_main, Bencher};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use serde_v8::utils::{js_exec, v8_do};
|
use serde_v8::utils::{js_exec, v8_do};
|
||||||
|
use serde_v8::ByteString;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
struct MathOp {
|
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!(
|
benchmark_group!(
|
||||||
benches,
|
benches,
|
||||||
de_struct_v8,
|
de_struct_v8,
|
||||||
|
@ -152,6 +172,8 @@ benchmark_group!(
|
||||||
de_tuple_v8,
|
de_tuple_v8,
|
||||||
de_tuple_json,
|
de_tuple_json,
|
||||||
de_tuple_v8_opt,
|
de_tuple_v8_opt,
|
||||||
|
de_bstr_v8_12_b,
|
||||||
|
de_bstr_v8_1024_b,
|
||||||
);
|
);
|
||||||
|
|
||||||
benchmark_main!(benches);
|
benchmark_main!(benches);
|
||||||
|
|
|
@ -4,6 +4,7 @@ use bencher::{benchmark_group, benchmark_main, Bencher};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use serde_v8::utils::v8_do;
|
use serde_v8::utils::v8_do;
|
||||||
|
use serde_v8::ByteString;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct MathOp {
|
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!(
|
benchmark_group!(
|
||||||
benches,
|
benches,
|
||||||
ser_struct_v8,
|
ser_struct_v8,
|
||||||
|
@ -102,5 +123,7 @@ benchmark_group!(
|
||||||
ser_tuple_v8,
|
ser_tuple_v8,
|
||||||
ser_tuple_json,
|
ser_tuple_json,
|
||||||
ser_struct_v8_manual,
|
ser_struct_v8_manual,
|
||||||
|
ser_bstr_12_b,
|
||||||
|
ser_bstr_1024_b,
|
||||||
);
|
);
|
||||||
benchmark_main!(benches);
|
benchmark_main!(benches);
|
||||||
|
|
|
@ -370,25 +370,25 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
|
||||||
|
|
||||||
// Magic ByteString
|
// Magic ByteString
|
||||||
if name == magic::bytestring::NAME {
|
if name == magic::bytestring::NAME {
|
||||||
if let Some(v8_string) = self.input.to_string(self.scope) {
|
let v8str = v8::Local::<v8::String>::try_from(self.input)
|
||||||
if v8_string.contains_only_onebyte() {
|
.map_err(|_| Error::ExpectedString)?;
|
||||||
let mut buffer: Vec<u8> = vec![0u8; v8_string.length()];
|
if !v8str.contains_only_onebyte() {
|
||||||
let written = v8_string.write_one_byte(
|
return Err(Error::ExpectedLatin1);
|
||||||
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 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
|
// Regular struct
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub enum Error {
|
||||||
ExpectedBuffer,
|
ExpectedBuffer,
|
||||||
|
|
||||||
ExpectedUtf8,
|
ExpectedUtf8,
|
||||||
|
ExpectedLatin1,
|
||||||
|
|
||||||
LengthMismatch,
|
LengthMismatch,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use serde::Deserialize;
|
||||||
|
|
||||||
use serde_v8::utils::{js_exec, v8_do};
|
use serde_v8::utils::{js_exec, v8_do};
|
||||||
use serde_v8::Buffer;
|
use serde_v8::Buffer;
|
||||||
|
use serde_v8::ByteString;
|
||||||
use serde_v8::Error;
|
use serde_v8::Error;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
|
@ -311,3 +312,7 @@ detest!(
|
||||||
b: "".into()
|
b: "".into()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
detest!(de_bstr, ByteString, "'hello'", ByteString("hello".into()));
|
||||||
|
defail!(defail_bstr, ByteString, "'👋bye'", |e| e
|
||||||
|
== Err(Error::ExpectedLatin1));
|
||||||
|
|
Loading…
Add table
Reference in a new issue