From 878599ca7c4eb7636b6d025e669b39651f5ba1d0 Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Sun, 4 Apr 2021 00:42:16 +0200 Subject: [PATCH] perf(serde_v8): drop need for RC in serializer (#9987) Which substantially improves the performance of to_v8() by removing Rc's overhead (extra allocs, drops, checks, etc...) --- serde_v8/src/ser.rs | 126 ++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/serde_v8/src/ser.rs b/serde_v8/src/ser.rs index 13a5c1d1cb..54c1be5e48 100644 --- a/serde_v8/src/ser.rs +++ b/serde_v8/src/ser.rs @@ -4,7 +4,6 @@ use serde::ser; use serde::ser::{Impossible, Serialize}; use std::cell::RefCell; -use std::rc::Rc; use crate::error::{Error, Result}; use crate::keys::v8_struct_key; @@ -13,31 +12,35 @@ use crate::magic; type JsValue<'s> = v8::Local<'s, v8::Value>; type JsResult<'s> = Result>; -type ScopePtr<'a, 'b> = Rc>>; +type ScopePtr<'a, 'b, 'c> = &'c RefCell>; pub fn to_v8<'a, T>(scope: &mut v8::HandleScope<'a>, input: T) -> JsResult<'a> where T: Serialize, { let subscope = v8::EscapableHandleScope::new(scope); - let scopeptr = Rc::new(RefCell::new(subscope)); - let serializer = Serializer::new(scopeptr.clone()); + let scopeptr = RefCell::new(subscope); + let serializer = Serializer::new(&scopeptr); let x = input.serialize(serializer)?; - let x = scopeptr.clone().borrow_mut().escape(x); + let x = scopeptr.borrow_mut().escape(x); Ok(x) } /// Wraps other serializers into an enum tagged variant form. /// Uses {"Variant": ...payload...} for compatibility with serde-json. -pub struct VariantSerializer<'a, 'b, S> { +pub struct VariantSerializer<'a, 'b, 'c, S> { variant: &'static str, inner: S, - scope: ScopePtr<'a, 'b>, + scope: ScopePtr<'a, 'b, 'c>, } -impl<'a, 'b, S> VariantSerializer<'a, 'b, S> { - pub fn new(scope: ScopePtr<'a, 'b>, variant: &'static str, inner: S) -> Self { +impl<'a, 'b, 'c, S> VariantSerializer<'a, 'b, 'c, S> { + pub fn new( + scope: ScopePtr<'a, 'b, 'c>, + variant: &'static str, + inner: S, + ) -> Self { Self { scope, variant, @@ -55,7 +58,8 @@ impl<'a, 'b, S> VariantSerializer<'a, 'b, S> { } } -impl<'a, 'b, S> ser::SerializeTupleVariant for VariantSerializer<'a, 'b, S> +impl<'a, 'b, 'c, S> ser::SerializeTupleVariant + for VariantSerializer<'a, 'b, 'c, S> where S: ser::SerializeTupleStruct, Error = Error>, { @@ -74,7 +78,8 @@ where } } -impl<'a, 'b, S> ser::SerializeStructVariant for VariantSerializer<'a, 'b, S> +impl<'a, 'b, 'c, S> ser::SerializeStructVariant + for VariantSerializer<'a, 'b, 'c, S> where S: ser::SerializeStruct, Error = Error>, { @@ -94,14 +99,14 @@ where } } -pub struct ArraySerializer<'a, 'b> { - // serializer: Serializer<'a, 'b>, +pub struct ArraySerializer<'a, 'b, 'c> { + // serializer: Serializer<'a, 'b, 'c>, pending: Vec>, - scope: ScopePtr<'a, 'b>, + scope: ScopePtr<'a, 'b, 'c>, } -impl<'a, 'b> ArraySerializer<'a, 'b> { - pub fn new(scope: ScopePtr<'a, 'b>) -> Self { +impl<'a, 'b, 'c> ArraySerializer<'a, 'b, 'c> { + pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { // let serializer = Serializer::new(scope); Self { scope, @@ -111,7 +116,7 @@ impl<'a, 'b> ArraySerializer<'a, 'b> { } } -impl<'a, 'b> ser::SerializeSeq for ArraySerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeSeq for ArraySerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -119,7 +124,7 @@ impl<'a, 'b> ser::SerializeSeq for ArraySerializer<'a, 'b> { &mut self, value: &T, ) -> Result<()> { - let x = value.serialize(Serializer::new(self.scope.clone()))?; + let x = value.serialize(Serializer::new(self.scope))?; self.pending.push(x); Ok(()) } @@ -132,7 +137,7 @@ impl<'a, 'b> ser::SerializeSeq for ArraySerializer<'a, 'b> { } } -impl<'a, 'b> ser::SerializeTuple for ArraySerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeTuple for ArraySerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -148,7 +153,7 @@ impl<'a, 'b> ser::SerializeTuple for ArraySerializer<'a, 'b> { } } -impl<'a, 'b> ser::SerializeTupleStruct for ArraySerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeTupleStruct for ArraySerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -164,19 +169,19 @@ impl<'a, 'b> ser::SerializeTupleStruct for ArraySerializer<'a, 'b> { } } -pub struct ObjectSerializer<'a, 'b> { - scope: ScopePtr<'a, 'b>, +pub struct ObjectSerializer<'a, 'b, 'c> { + scope: ScopePtr<'a, 'b, 'c>, obj: v8::Local<'a, v8::Object>, } -impl<'a, 'b> ObjectSerializer<'a, 'b> { - pub fn new(scope: ScopePtr<'a, 'b>) -> Self { +impl<'a, 'b, 'c> ObjectSerializer<'a, 'b, 'c> { + pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { let obj = v8::Object::new(&mut *scope.borrow_mut()); Self { scope, obj } } } -impl<'a, 'b> ser::SerializeStruct for ObjectSerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeStruct for ObjectSerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -185,7 +190,7 @@ impl<'a, 'b> ser::SerializeStruct for ObjectSerializer<'a, 'b> { key: &'static str, value: &T, ) -> Result<()> { - let value = value.serialize(Serializer::new(self.scope.clone()))?; + let value = value.serialize(Serializer::new(self.scope))?; let scope = &mut *self.scope.borrow_mut(); let key = v8_struct_key(scope, key).into(); self.obj.set(scope, key, value); @@ -197,12 +202,12 @@ impl<'a, 'b> ser::SerializeStruct for ObjectSerializer<'a, 'b> { } } -pub struct MagicSerializer<'a, 'b> { - scope: ScopePtr<'a, 'b>, +pub struct MagicSerializer<'a, 'b, 'c> { + scope: ScopePtr<'a, 'b, 'c>, v8_value: Option>, } -impl<'a, 'b> ser::SerializeStruct for MagicSerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeStruct for MagicSerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -214,9 +219,7 @@ impl<'a, 'b> ser::SerializeStruct for MagicSerializer<'a, 'b> { if key != magic::FIELD { unreachable!(); } - let v8_value = value.serialize(MagicTransmuter { - _scope: self.scope.clone(), - })?; + let v8_value = value.serialize(MagicTransmuter { _scope: self.scope })?; self.v8_value = Some(v8_value); Ok(()) } @@ -227,12 +230,12 @@ impl<'a, 'b> ser::SerializeStruct for MagicSerializer<'a, 'b> { } // Dispatches between magic and regular struct serializers -pub enum StructSerializers<'a, 'b> { - Magic(MagicSerializer<'a, 'b>), - Regular(ObjectSerializer<'a, 'b>), +pub enum StructSerializers<'a, 'b, 'c> { + Magic(MagicSerializer<'a, 'b, 'c>), + Regular(ObjectSerializer<'a, 'b, 'c>), } -impl<'a, 'b> ser::SerializeStruct for StructSerializers<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; @@ -256,14 +259,14 @@ impl<'a, 'b> ser::SerializeStruct for StructSerializers<'a, 'b> { } // Serializes to JS Objects, NOT JS Maps ... -pub struct MapSerializer<'a, 'b> { - scope: ScopePtr<'a, 'b>, +pub struct MapSerializer<'a, 'b, 'c> { + scope: ScopePtr<'a, 'b, 'c>, obj: v8::Local<'a, v8::Object>, next_key: Option>, } -impl<'a, 'b> MapSerializer<'a, 'b> { - pub fn new(scope: ScopePtr<'a, 'b>) -> Self { +impl<'a, 'b, 'c> MapSerializer<'a, 'b, 'c> { + pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { let obj = v8::Object::new(&mut *scope.borrow_mut()); Self { scope, @@ -273,13 +276,13 @@ impl<'a, 'b> MapSerializer<'a, 'b> { } } -impl<'a, 'b> ser::SerializeMap for MapSerializer<'a, 'b> { +impl<'a, 'b, 'c> ser::SerializeMap for MapSerializer<'a, 'b, 'c> { type Ok = JsValue<'a>; type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<()> { debug_assert!(self.next_key.is_none()); - self.next_key = Some(key.serialize(Serializer::new(self.scope.clone()))?); + self.next_key = Some(key.serialize(Serializer::new(self.scope))?); Ok(()) } @@ -287,7 +290,7 @@ impl<'a, 'b> ser::SerializeMap for MapSerializer<'a, 'b> { &mut self, value: &T, ) -> Result<()> { - let v8_value = value.serialize(Serializer::new(self.scope.clone()))?; + let v8_value = value.serialize(Serializer::new(self.scope))?; let scope = &mut *self.scope.borrow_mut(); self.obj.set(scope, self.next_key.take().unwrap(), v8_value); Ok(()) @@ -299,13 +302,12 @@ impl<'a, 'b> ser::SerializeMap for MapSerializer<'a, 'b> { } } -#[derive(Clone)] -pub struct Serializer<'a, 'b> { - scope: ScopePtr<'a, 'b>, +pub struct Serializer<'a, 'b, 'c> { + scope: ScopePtr<'a, 'b, 'c>, } -impl<'a, 'b> Serializer<'a, 'b> { - pub fn new(scope: ScopePtr<'a, 'b>) -> Self { +impl<'a, 'b, 'c> Serializer<'a, 'b, 'c> { + pub fn new(scope: ScopePtr<'a, 'b, 'c>) -> Self { Serializer { scope } } } @@ -318,19 +320,19 @@ macro_rules! forward_to { }; } -impl<'a, 'b> ser::Serializer for Serializer<'a, 'b> { +impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> { type Ok = v8::Local<'a, v8::Value>; type Error = Error; - type SerializeSeq = ArraySerializer<'a, 'b>; - type SerializeTuple = ArraySerializer<'a, 'b>; - type SerializeTupleStruct = ArraySerializer<'a, 'b>; + type SerializeSeq = ArraySerializer<'a, 'b, 'c>; + type SerializeTuple = ArraySerializer<'a, 'b, 'c>; + type SerializeTupleStruct = ArraySerializer<'a, 'b, 'c>; type SerializeTupleVariant = - VariantSerializer<'a, 'b, ArraySerializer<'a, 'b>>; - type SerializeMap = MapSerializer<'a, 'b>; - type SerializeStruct = StructSerializers<'a, 'b>; + VariantSerializer<'a, 'b, 'c, ArraySerializer<'a, 'b, 'c>>; + type SerializeMap = MapSerializer<'a, 'b, 'c>; + type SerializeStruct = StructSerializers<'a, 'b, 'c>; type SerializeStructVariant = - VariantSerializer<'a, 'b, StructSerializers<'a, 'b>>; + VariantSerializer<'a, 'b, 'c, StructSerializers<'a, 'b, 'c>>; forward_to! { serialize_i8(i8, serialize_i32, 'a); @@ -416,7 +418,7 @@ impl<'a, 'b> ser::Serializer for Serializer<'a, 'b> { variant: &'static str, value: &T, ) -> JsResult<'a> { - let scope = self.scope.clone(); + let scope = self.scope; let x = self.serialize_newtype_struct(variant, value)?; VariantSerializer::new(scope, variant, x).end(Ok) } @@ -446,7 +448,7 @@ impl<'a, 'b> ser::Serializer for Serializer<'a, 'b> { len: usize, ) -> Result { Ok(VariantSerializer::new( - self.scope.clone(), + self.scope, variant, self.serialize_tuple_struct(variant, len)?, )) @@ -484,7 +486,7 @@ impl<'a, 'b> ser::Serializer for Serializer<'a, 'b> { variant: &'static str, len: usize, ) -> Result { - let scope = self.scope.clone(); + let scope = self.scope; let x = self.serialize_struct(variant, len)?; Ok(VariantSerializer::new(scope, variant, x)) } @@ -500,11 +502,11 @@ macro_rules! not_reachable { /// A VERY hackish serde::Serializer /// that exists solely to transmute a u64 to a serde_v8::Value -struct MagicTransmuter<'a, 'b> { - _scope: ScopePtr<'a, 'b>, +struct MagicTransmuter<'a, 'b, 'c> { + _scope: ScopePtr<'a, 'b, 'c>, } -impl<'a, 'b> ser::Serializer for MagicTransmuter<'a, 'b> { +impl<'a, 'b, 'c> ser::Serializer for MagicTransmuter<'a, 'b, 'c> { type Ok = v8::Local<'a, v8::Value>; type Error = Error;