forked from denoland/deno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
serde_v8: restore ser/de benches (denoland#9939)
- Loading branch information
Showing
4 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
use bencher::{benchmark_group, benchmark_main, Bencher}; | ||
|
||
use rusty_v8 as v8; | ||
use std::convert::TryFrom; | ||
|
||
use serde::Deserialize; | ||
|
||
use serde_v8::utils::{js_exec, v8_do}; | ||
|
||
#[derive(Debug, Deserialize, PartialEq)] | ||
struct MathOp { | ||
arg1: u64, | ||
arg2: u64, | ||
operator: Option<String>, | ||
} | ||
|
||
fn dedo( | ||
code: &str, | ||
f: impl FnOnce(&mut v8::HandleScope, v8::Local<v8::Value>), | ||
) { | ||
v8_do(|| { | ||
let isolate = &mut v8::Isolate::new(v8::CreateParams::default()); | ||
let handle_scope = &mut v8::HandleScope::new(isolate); | ||
let context = v8::Context::new(handle_scope); | ||
let scope = &mut v8::ContextScope::new(handle_scope, context); | ||
let v = js_exec(scope, code); | ||
|
||
f(scope, v); | ||
}) | ||
} | ||
|
||
fn dedo_json(code: &str, f: impl FnOnce(String)) { | ||
let code = format!("JSON.stringify({})", code); | ||
dedo(&code[..], |scope, v| { | ||
let s: String = serde_v8::from_v8(scope, v).unwrap(); | ||
f(s); | ||
}) | ||
} | ||
|
||
fn de_struct_v8(b: &mut Bencher) { | ||
dedo("({arg1: 10, arg2: 123 })", |scope, obj| { | ||
let mut total = 0; | ||
b.iter(move || { | ||
let op: MathOp = serde_v8::from_v8(scope, obj).unwrap(); | ||
total = total + op.arg1 + op.arg2; | ||
}); | ||
}); | ||
} | ||
|
||
fn de_struct_v8_opt(b: &mut Bencher) { | ||
dedo("({arg1: 10, arg2: 123 })", |scope, v| { | ||
let k_arg1 = v8::String::new(scope, "arg1").unwrap().into(); | ||
let k_arg2 = v8::String::new(scope, "arg2").unwrap().into(); | ||
let obj = v8::Local::<v8::Object>::try_from(v).unwrap(); | ||
let mut total = 0; | ||
b.iter(move || { | ||
let v_arg1 = obj.get(scope, k_arg1).unwrap(); | ||
let v_arg2 = obj.get(scope, k_arg2).unwrap(); | ||
let op = MathOp { | ||
arg1: serde_v8::from_v8(scope, v_arg1).unwrap(), | ||
arg2: serde_v8::from_v8(scope, v_arg2).unwrap(), | ||
operator: None, | ||
}; | ||
total = total + op.arg1 + op.arg2; | ||
}); | ||
}); | ||
} | ||
|
||
fn de_struct_json(b: &mut Bencher) { | ||
dedo_json("({arg1: 10, arg2: 123 })", |s| { | ||
let mut total = 0; | ||
b.iter(move || { | ||
let op: MathOp = serde_json::from_str(&s).unwrap(); | ||
total = total + op.arg1 + op.arg2; | ||
}); | ||
}); | ||
} | ||
|
||
fn de_struct_json_deopt(b: &mut Bencher) { | ||
// JSON.stringify() in loop (semi-simulating ABI loop) | ||
dedo("({arg1: 10, arg2: 123 })", |scope, obj| { | ||
let mut total = 0; | ||
b.iter(move || { | ||
let mut scope = v8::HandleScope::new(scope); | ||
let s = v8::json::stringify(&mut scope, obj).unwrap(); | ||
let rs = s.to_rust_string_lossy(&mut scope); | ||
let op: MathOp = serde_json::from_str(&rs).unwrap(); | ||
total = total + op.arg1 + op.arg2; | ||
}); | ||
}); | ||
} | ||
|
||
macro_rules! dualbench { | ||
($v8_fn:ident, $json_fn:ident, $src:expr, $t:ty) => { | ||
fn $v8_fn(b: &mut Bencher) { | ||
dedo($src, |scope, v| { | ||
b.iter(move || { | ||
let _: $t = serde_v8::from_v8(scope, v).unwrap(); | ||
}); | ||
}); | ||
} | ||
|
||
fn $json_fn(b: &mut Bencher) { | ||
dedo_json($src, |s| { | ||
b.iter(move || { | ||
let _: $t = serde_json::from_str(&s).unwrap(); | ||
}); | ||
}); | ||
} | ||
}; | ||
} | ||
|
||
dualbench!(de_bool_v8, de_bool_json, "true", bool); | ||
dualbench!(de_int_v8, de_int_json, "12345", u32); | ||
dualbench!( | ||
de_array_v8, | ||
de_array_json, | ||
"[1,2,3,4,5,6,7,8,9,10]", | ||
Vec<u32> | ||
); | ||
dualbench!(de_str_v8, de_str_json, "'hello world'", String); | ||
dualbench!(de_tuple_v8, de_tuple_json, "[1,false]", (u8, bool)); | ||
|
||
fn de_tuple_v8_opt(b: &mut Bencher) { | ||
dedo("[1,false]", |scope, obj| { | ||
let arr = v8::Local::<v8::Array>::try_from(obj).unwrap(); | ||
let obj = v8::Local::<v8::Object>::from(arr); | ||
|
||
b.iter(move || { | ||
let v1 = obj.get_index(scope, 0).unwrap(); | ||
let v2 = obj.get_index(scope, 1).unwrap(); | ||
let _: (u8, bool) = ( | ||
serde_v8::from_v8(scope, v1).unwrap(), | ||
serde_v8::from_v8(scope, v2).unwrap(), | ||
); | ||
}); | ||
}); | ||
} | ||
|
||
benchmark_group!( | ||
benches, | ||
de_struct_v8, | ||
de_struct_v8_opt, | ||
de_struct_json, | ||
de_struct_json_deopt, | ||
de_bool_v8, | ||
de_bool_json, | ||
de_int_v8, | ||
de_int_json, | ||
de_array_v8, | ||
de_array_json, | ||
de_str_v8, | ||
de_str_json, | ||
de_tuple_v8, | ||
de_tuple_json, | ||
de_tuple_v8_opt, | ||
); | ||
|
||
benchmark_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use bencher::{benchmark_group, benchmark_main, Bencher}; | ||
|
||
use rusty_v8 as v8; | ||
|
||
use serde::Serialize; | ||
|
||
use serde_v8::utils::v8_do; | ||
|
||
#[derive(Serialize)] | ||
struct MathOp { | ||
arg1: u64, | ||
arg2: u64, | ||
operator: Option<String>, | ||
} | ||
|
||
fn serdo(f: impl FnOnce(&mut v8::HandleScope)) { | ||
v8_do(|| { | ||
let isolate = &mut v8::Isolate::new(v8::CreateParams::default()); | ||
let handle_scope = &mut v8::HandleScope::new(isolate); | ||
let context = v8::Context::new(handle_scope); | ||
let scope = &mut v8::ContextScope::new(handle_scope, context); | ||
|
||
f(scope); | ||
}) | ||
} | ||
|
||
macro_rules! dualbench { | ||
($v8_fn:ident, $json_fn:ident, $src:expr) => { | ||
fn $v8_fn(b: &mut Bencher) { | ||
serdo(|scope| { | ||
let v = $src; | ||
b.iter(move || { | ||
let _ = serde_v8::to_v8(scope, &v).unwrap(); | ||
}); | ||
}); | ||
} | ||
|
||
fn $json_fn(b: &mut Bencher) { | ||
let v = $src; | ||
b.iter(move || { | ||
let _ = serde_json::to_string(&v).unwrap(); | ||
}); | ||
} | ||
}; | ||
} | ||
|
||
dualbench!( | ||
ser_struct_v8, | ||
ser_struct_json, | ||
MathOp { | ||
arg1: 10, | ||
arg2: 123, | ||
operator: None | ||
} | ||
); | ||
dualbench!(ser_bool_v8, ser_bool_json, true); | ||
dualbench!(ser_int_v8, ser_int_json, 12345); | ||
dualbench!( | ||
ser_array_v8, | ||
ser_array_json, | ||
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | ||
); | ||
dualbench!(ser_str_v8, ser_str_json, "hello world"); | ||
dualbench!(ser_tuple_v8, ser_tuple_json, (1, false)); | ||
|
||
fn ser_struct_v8_manual(b: &mut Bencher) { | ||
serdo(|scope| { | ||
let v = MathOp { | ||
arg1: 10, | ||
arg2: 123, | ||
operator: None, | ||
}; | ||
b.iter(|| { | ||
let obj = v8::Object::new(scope); | ||
let k1 = v8::String::new(scope, "arg1").unwrap(); | ||
let k2 = v8::String::new(scope, "arg2").unwrap(); | ||
let k3 = v8::String::new(scope, "operator").unwrap(); | ||
// let k1 = v8::String::new_from_utf8(scope, "arg1".as_ref(), v8::NewStringType::Internalized).unwrap(); | ||
// let k2 = v8::String::new_from_utf8(scope, "arg2".as_ref(), v8::NewStringType::Internalized).unwrap(); | ||
// let k3 = v8::String::new_from_utf8(scope, "operator".as_ref(), v8::NewStringType::Internalized).unwrap(); | ||
let v1 = v8::Number::new(scope, v.arg1 as f64); | ||
let v2 = v8::Number::new(scope, v.arg2 as f64); | ||
let v3 = v8::null(scope); | ||
obj.set(scope, k1.into(), v1.into()).unwrap(); | ||
obj.set(scope, k2.into(), v2.into()).unwrap(); | ||
obj.set(scope, k3.into(), v3.into()).unwrap(); | ||
}); | ||
}); | ||
} | ||
|
||
benchmark_group!( | ||
benches, | ||
ser_struct_v8, | ||
ser_struct_json, | ||
ser_bool_v8, | ||
ser_bool_json, | ||
ser_int_v8, | ||
ser_int_json, | ||
ser_array_v8, | ||
ser_array_json, | ||
ser_str_v8, | ||
ser_str_json, | ||
ser_tuple_v8, | ||
ser_tuple_json, | ||
ser_struct_v8_manual, | ||
); | ||
benchmark_main!(benches); |