summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-03-17 16:15:27 -0600
committerGitHub <noreply@github.com>2023-03-17 22:15:27 +0000
commit3487fde236d0852a8b0672c293fa41a741f471e8 (patch)
treeaf466368147a08b787080446319a3a46a60ee37d /core
parente55b448730160a6e4df9815a268d4049ac89deab (diff)
perf(core) Reduce copying and cloning in extension initialization (#18252)
Follow-up to #18210: * we are passing the generated `cfg` object into the state function rather than passing individual config fields * reduce cloning dramatically by making the state_fn `FnOnce` * `take` for `ExtensionBuilder` to avoid more unnecessary copies * renamed `config` to `options`
Diffstat (limited to 'core')
-rw-r--r--core/extensions.rs86
-rw-r--r--core/runtime.rs8
2 files changed, 68 insertions, 26 deletions
diff --git a/core/extensions.rs b/core/extensions.rs
index 71b9cdb4f..53ce57be8 100644
--- a/core/extensions.rs
+++ b/core/extensions.rs
@@ -42,7 +42,7 @@ pub struct ExtensionFileSource {
}
pub type OpFnRef = v8::FunctionCallback;
pub type OpMiddlewareFn = dyn Fn(OpDecl) -> OpDecl;
-pub type OpStateFn = dyn Fn(&mut OpState);
+pub type OpStateFn = dyn FnOnce(&mut OpState);
pub type OpEventLoopFn = dyn Fn(Rc<RefCell<OpState>>, &mut Context) -> bool;
pub struct OpDecl {
@@ -164,7 +164,7 @@ macro_rules! extension {
$(, esm = [ $( dir $dir_esm:literal , )? $( $esm:literal ),* $(,)? ] )?
$(, esm_setup_script = $esm_setup_script:expr )?
$(, js = [ $( dir $dir_js:literal , )? $( $js:literal ),* $(,)? ] )?
- $(, config = { $( $config_id:ident : $config_type:ty ),* $(,)? } )?
+ $(, options = { $( $options_id:ident : $options_type:ty ),* $(,)? } )?
$(, middleware = $middleware_fn:expr )?
$(, state = $state_fn:expr )?
$(, event_loop_middleware = $event_loop_middleware_fn:ident )?
@@ -227,13 +227,13 @@ macro_rules! extension {
// Includes the state and middleware functions, if defined.
#[inline(always)]
#[allow(unused_variables)]
- fn with_state_and_middleware$( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder, $( $( $config_id : $config_type ),* )? ) {
+ fn with_state_and_middleware$( < $( $param : $type + Clone + 'static ),+ > )?(ext: &mut $crate::ExtensionBuilder, $( $( $options_id : $options_type ),* )? ) {
#[allow(unused_variables)]
- let config = $crate::extension!(! __config__ $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $config_id : $config_type ),* } )? );
+ let config = $crate::extension!(! __config__ $( parameters = [ $( $param : $type ),* ] )? $( config = { $( $options_id : $options_type ),* } )? );
$(
ext.state(move |state: &mut $crate::OpState| {
- config.clone().call_callback(state, $state_fn)
+ config.call_callback(state, $state_fn)
});
)?
@@ -259,57 +259,78 @@ macro_rules! extension {
Self::with_js(&mut ext);
Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
Self::with_customizer(&mut ext);
- ext.build()
+ ext.take()
}
#[allow(dead_code)]
- pub fn init_ops_and_esm $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension {
+ pub fn init_ops_and_esm $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension {
let mut ext = Self::ext();
// If esm or JS was specified, add JS files
Self::with_js(&mut ext);
Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
- Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? );
+ Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $options_id , )* )? );
Self::with_customizer(&mut ext);
- ext.build()
+ ext.take()
}
#[allow(dead_code)]
- pub fn init_ops $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $config_id : $config_type ),* )? ) -> $crate::Extension {
+ pub fn init_ops $( < $( $param : $type + Clone + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension {
let mut ext = Self::ext();
Self::with_ops $( ::<($( $param ),+)> )?(&mut ext);
- Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $config_id , )* )? );
+ Self::with_state_and_middleware $( ::<($( $param ),+)> )?(&mut ext, $( $( $options_id , )* )? );
Self::with_customizer(&mut ext);
- ext.build()
+ ext.take()
}
}
};
- (! __config__ $( parameters = [ $( $param:ident : $type:ident ),+ ] )? $( config = { $( $config_id:ident : $config_type:ty ),* } )? ) => {
+ // This branch of the macro generates a config object that calls the state function with itself.
+ (! __config__ $( parameters = [ $( $param:ident : $type:ident ),+ ] )? config = { $( $options_id:ident : $options_type:ty ),* } ) => {
{
#[doc(hidden)]
- #[derive(Clone)]
struct Config $( < $( $param : $type + Clone + 'static ),+ > )? {
- $( $( pub $config_id : $config_type , )* )?
+ $( pub $options_id : $options_type , )*
$( __phantom_data: ::std::marker::PhantomData<($( $param ),+)>, )?
}
impl $( < $( $param : $type + Clone + 'static ),+ > )? Config $( < $( $param ),+ > )? {
- /// Call a function of |state, ...| using the fields of this configuration structure.
+ /// Call a function of |state, cfg| using this configuration structure.
#[allow(dead_code)]
#[doc(hidden)]
#[inline(always)]
- fn call_callback<F: Fn(&mut $crate::OpState, $( $( $config_type ),* )?)>(self, state: &mut $crate::OpState, f: F) {
- f(state, $( $( self. $config_id ),* )? )
+ fn call_callback<F: Fn(&mut $crate::OpState, Self)>(self, state: &mut $crate::OpState, f: F) {
+ f(state, self)
}
}
Config {
- $( $( $config_id , )* )?
+ $( $options_id , )*
$( __phantom_data: ::std::marker::PhantomData::<($( $param ),+)>::default() )?
}
}
};
+ // This branch of the macro generates an empty config object that doesn't actually make any callbacks on the state function.
+ (! __config__ $( parameters = [ $( $param:ident : $type:ident ),+ ] )? ) => {
+ {
+ #[doc(hidden)]
+ struct Config {
+ }
+
+ impl Config {
+ /// Call a function of |state| using the fields of this configuration structure.
+ #[allow(dead_code)]
+ #[doc(hidden)]
+ #[inline(always)]
+ fn call_callback<F: Fn(&mut $crate::OpState)>(self, state: &mut $crate::OpState, f: F) {
+ f(state)
+ }
+ }
+
+ Config {}
+ }
+ };
+
(! __ops__ $ext:ident __eot__) => {
};
@@ -409,8 +430,8 @@ impl Extension {
}
/// Allows setting up the initial op-state of an isolate at startup.
- pub fn init_state(&self, state: &mut OpState) {
- if let Some(op_fn) = &self.opstate_fn {
+ pub fn init_state(&mut self, state: &mut OpState) {
+ if let Some(op_fn) = self.opstate_fn.take() {
op_fn(state);
}
}
@@ -499,7 +520,7 @@ impl ExtensionBuilder {
pub fn state<F>(&mut self, opstate_fn: F) -> &mut Self
where
- F: Fn(&mut OpState) + 'static,
+ F: FnOnce(&mut OpState) + 'static,
{
self.state = Some(Box::new(opstate_fn));
self
@@ -521,6 +542,27 @@ impl ExtensionBuilder {
self
}
+ /// Consume the [`ExtensionBuilder`] and return an [`Extension`].
+ pub fn take(self) -> Extension {
+ let js_files = Some(self.js);
+ let esm_files = Some(self.esm);
+ let ops = Some(self.ops);
+ let deps = Some(self.deps);
+ Extension {
+ js_files,
+ esm_files,
+ esm_entry_point: self.esm_entry_point,
+ ops,
+ opstate_fn: self.state,
+ middleware_fn: self.middleware,
+ event_loop_middleware: self.event_loop_middleware,
+ initialized: false,
+ enabled: true,
+ name: self.name,
+ deps,
+ }
+ }
+
pub fn build(&mut self) -> Extension {
let js_files = Some(std::mem::take(&mut self.js));
let esm_files = Some(std::mem::take(&mut self.esm));
diff --git a/core/runtime.rs b/core/runtime.rs
index 1ea9c0168..0531e861c 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -2731,14 +2731,14 @@ pub mod tests {
deno_core::extension!(
test_ext,
ops = [op_test],
- config = {
+ options = {
mode: Mode,
dispatch_count: Arc<AtomicUsize>,
},
- state = |state, mode, dispatch_count| {
+ state = |state, options| {
state.put(TestState {
- mode,
- dispatch_count
+ mode: options.mode,
+ dispatch_count: options.dispatch_count
})
}
);