From fec1b2a5a4324a7eecdfbb2471931f3b6b0139c5 Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Wed, 31 Mar 2021 16:37:38 +0200 Subject: refactor: new optimized op-layer using serde_v8 (#9843) - Improves op performance. - Handle op-metadata (errors, promise IDs) explicitly in the op-layer vs per op-encoding (aka: out-of-payload). - Remove shared queue & custom "asyncHandlers", all async values are returned in batches via js_recv_cb. - The op-layer should be thought of as simple function calls with little indirection or translation besides the conceptually straightforward serde_v8 bijections. - Preserve concepts of json/bin/min as semantic groups of their inputs/outputs instead of their op-encoding strategy, preserving these groups will also facilitate partial transitions over to v8 Fast API for the "min" and "bin" groups --- core/ops_json.rs | 104 +++++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 57 deletions(-) (limited to 'core/ops_json.rs') diff --git a/core/ops_json.rs b/core/ops_json.rs index 0ef91ed33..ee336830b 100644 --- a/core/ops_json.rs +++ b/core/ops_json.rs @@ -1,37 +1,19 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::error::type_error; use crate::error::AnyError; +use crate::serialize_op_result; use crate::BufVec; use crate::Op; use crate::OpFn; +use crate::OpPayload; use crate::OpState; use crate::ZeroCopyBuf; use serde::de::DeserializeOwned; use serde::Serialize; use std::cell::RefCell; -use std::convert::TryInto; use std::future::Future; use std::rc::Rc; -fn json_serialize_op_result( - request_id: Option, - result: Result, - get_error_class_fn: crate::runtime::GetErrorClassFn, -) -> Box<[u8]> { - let value = match result { - Ok(v) => serde_json::json!({ "ok": v, "requestId": request_id }), - Err(err) => serde_json::json!({ - "requestId": request_id, - "err": { - "className": (get_error_class_fn)(&err), - "message": err.to_string(), - } - }), - }; - serde_json::to_vec(&value).unwrap().into_boxed_slice() -} - /// Creates an op that passes data synchronously using JSON. /// /// The provided function `op_fn` has the following parameters: @@ -59,15 +41,20 @@ pub fn json_op_sync(op_fn: F) -> Box where F: Fn(&mut OpState, V, &mut [ZeroCopyBuf]) -> Result + 'static, V: DeserializeOwned, - R: Serialize, + R: Serialize + 'static, { - Box::new(move |state: Rc>, mut bufs: BufVec| -> Op { - let result = serde_json::from_slice(&bufs[0]) - .map_err(AnyError::from) - .and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs[1..])); - let buf = - json_serialize_op_result(None, result, state.borrow().get_error_class_fn); - Op::Sync(buf) + Box::new(move |state, payload, buf: Option| -> Op { + // For sig compat map Option to BufVec + let mut bufs: BufVec = match buf { + Some(b) => vec![b], + None => vec![], + } + .into(); + + let result = payload + .deserialize() + .and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs)); + Op::Sync(serialize_op_result(result, state)) }) } @@ -100,35 +87,38 @@ where F: Fn(Rc>, V, BufVec) -> R + 'static, V: DeserializeOwned, R: Future> + 'static, - RV: Serialize, + RV: Serialize + 'static, { - let try_dispatch_op = - move |state: Rc>, bufs: BufVec| -> Result { - let request_id = bufs[0] - .get(0..8) - .map(|b| u64::from_le_bytes(b.try_into().unwrap())) - .ok_or_else(|| type_error("missing or invalid `requestId`"))?; - let args = serde_json::from_slice(&bufs[0][8..])?; - let bufs = bufs[1..].into(); - use crate::futures::FutureExt; - let fut = op_fn(state.clone(), args, bufs).map(move |result| { - json_serialize_op_result( - Some(request_id), - result, - state.borrow().get_error_class_fn, - ) - }); - Ok(Op::Async(Box::pin(fut))) - }; - - Box::new(move |state: Rc>, bufs: BufVec| -> Op { - match try_dispatch_op(state.clone(), bufs) { - Ok(op) => op, - Err(err) => Op::Sync(json_serialize_op_result( - None, - Err::<(), AnyError>(err), - state.borrow().get_error_class_fn, - )), + let try_dispatch_op = move |state: Rc>, + p: OpPayload, + b: Option| + -> Result { + // For sig compat map Option to BufVec + let bufs: BufVec = match b { + Some(b) => vec![b], + None => vec![], } - }) + .into(); + // Parse args + let args = p.deserialize()?; + + use crate::futures::FutureExt; + let fut = op_fn(state.clone(), args, bufs) + .map(move |result| serialize_op_result(result, state)); + Ok(Op::Async(Box::pin(fut))) + }; + + Box::new( + move |state: Rc>, + p: OpPayload, + b: Option| + -> Op { + match try_dispatch_op(state.clone(), p, b) { + Ok(op) => op, + Err(err) => { + Op::Sync(serialize_op_result(Err::<(), AnyError>(err), state)) + } + } + }, + ) } -- cgit v1.2.3