From aa47324ee9c09fda894b0142314cafa9e92fed01 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Mon, 5 Aug 2024 21:34:51 +0100 Subject: [PATCH] Use pool for MultiValue container --- Cargo.toml | 2 +- src/multi.rs | 8 ++--- src/state/extra.rs | 7 +--- src/state/raw.rs | 19 ----------- src/state/util.rs | 1 - src/value.rs | 81 ++++++++++++++++++++++------------------------ 6 files changed, 45 insertions(+), 73 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 760205a6..042260fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "mlua" version = "0.10.0-beta.1" # remember to update mlua_derive authors = ["Aleksandr Orlenko ", "kyren "] -rust-version = "1.71" +rust-version = "1.79.0" edition = "2021" repository = "https://github.com/khvzak/mlua" documentation = "https://docs.rs/mlua" diff --git a/src/multi.rs b/src/multi.rs index 443c2658..f62f15a3 100644 --- a/src/multi.rs +++ b/src/multi.rs @@ -49,7 +49,7 @@ impl IntoLuaMulti for StdResult<(), E> { impl IntoLuaMulti for T { #[inline] fn into_lua_multi(self, lua: &Lua) -> Result { - let mut v = MultiValue::with_lua_and_capacity(lua, 1); + let mut v = MultiValue::with_capacity(1); v.push_back(self.into_lua(lua)?); Ok(v) } @@ -177,7 +177,7 @@ impl DerefMut for Variadic { impl IntoLuaMulti for Variadic { #[inline] fn into_lua_multi(self, lua: &Lua) -> Result { - let mut values = MultiValue::with_lua_and_capacity(lua, self.0.len()); + let mut values = MultiValue::with_capacity(self.0.len()); values.extend_from_values(self.0.into_iter().map(|val| val.into_lua(lua)))?; Ok(values) } @@ -198,8 +198,8 @@ macro_rules! impl_tuple { () => ( impl IntoLuaMulti for () { #[inline] - fn into_lua_multi(self, lua: &Lua) -> Result { - Ok(MultiValue::with_lua_and_capacity(lua, 0)) + fn into_lua_multi(self, _: &Lua) -> Result { + Ok(MultiValue::new()) } #[inline] diff --git a/src/state/extra.rs b/src/state/extra.rs index d3724e67..e8bbc646 100644 --- a/src/state/extra.rs +++ b/src/state/extra.rs @@ -1,10 +1,9 @@ use std::any::TypeId; use std::cell::UnsafeCell; -use std::rc::Rc; -// use std::collections::VecDeque; use std::mem::{self, MaybeUninit}; use std::os::raw::{c_int, c_void}; use std::ptr; +use std::rc::Rc; use std::sync::Arc; use parking_lot::Mutex; @@ -28,7 +27,6 @@ use super::{Lua, WeakLua}; static EXTRA_REGISTRY_KEY: u8 = 0; const WRAPPED_FAILURE_POOL_SIZE: usize = 64; -// const MULTIVALUE_POOL_SIZE: usize = 64; const REF_STACK_RESERVE: c_int = 1; /// Data associated with the Lua state. @@ -61,8 +59,6 @@ pub(crate) struct ExtraData { // Pool of `WrappedFailure` enums in the ref thread (as userdata) pub(super) wrapped_failure_pool: Vec, - // Pool of `MultiValue` containers - // multivalue_pool: Vec>, // Pool of `Thread`s (coroutines) for async execution #[cfg(feature = "async")] pub(super) thread_pool: Vec, @@ -162,7 +158,6 @@ impl ExtraData { ref_stack_top: ffi::lua_gettop(ref_thread), ref_free: Vec::new(), wrapped_failure_pool: Vec::with_capacity(WRAPPED_FAILURE_POOL_SIZE), - // multivalue_pool: Vec::with_capacity(MULTIVALUE_POOL_SIZE), #[cfg(feature = "async")] thread_pool: Vec::new(), wrapped_failure_mt_ptr, diff --git a/src/state/raw.rs b/src/state/raw.rs index fccf2540..959ccd64 100644 --- a/src/state/raw.rs +++ b/src/state/raw.rs @@ -496,25 +496,6 @@ impl RawLua { false } - // FIXME - // #[inline] - // pub(crate) fn pop_multivalue_from_pool(&self) -> Option> { - // let extra = unsafe { &mut *self.extra.get() }; - // extra.multivalue_pool.pop() - // } - - // FIXME - // #[inline] - // pub(crate) fn push_multivalue_to_pool(&self, mut multivalue: VecDeque) { - // let extra = unsafe { &mut *self.extra.get() }; - // if extra.multivalue_pool.len() < MULTIVALUE_POOL_SIZE { - // multivalue.clear(); - // extra - // .multivalue_pool - // .push(unsafe { mem::transmute(multivalue) }); - // } - // } - /// Pushes a value that implements `IntoLua` onto the Lua stack. /// /// Uses 2 stack spaces, does not call checkstack. diff --git a/src/state/util.rs b/src/state/util.rs index 9d557340..bb082c72 100644 --- a/src/state/util.rs +++ b/src/state/util.rs @@ -8,7 +8,6 @@ use crate::state::{ExtraData, RawLua}; use crate::util::{self, get_internal_metatable, WrappedFailure}; const WRAPPED_FAILURE_POOL_SIZE: usize = 64; -// const MULTIVALUE_POOL_SIZE: usize = 64; pub(super) struct StateGuard<'a>(&'a RawLua, *mut ffi::lua_State); diff --git a/src/value.rs b/src/value.rs index 2429910a..6f603199 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::cmp::Ordering; use std::collections::{vec_deque, HashSet, VecDeque}; use std::ops::{Deref, DerefMut}; @@ -23,7 +24,7 @@ use { crate::table::SerializableTable, rustc_hash::FxHashSet, serde::ser::{self, Serialize, Serializer}, - std::{cell::RefCell, rc::Rc, result::Result as StdResult}, + std::{rc::Rc, result::Result as StdResult}, }; /// A dynamically typed Lua value. The `String`, `Table`, `Function`, `Thread`, and `UserData` @@ -744,21 +745,25 @@ pub trait FromLua: Sized { } } +// Per-thread size of the VecDeque pool for MultiValue container. +const MULTIVALUE_POOL_SIZE: usize = 32; + +thread_local! { + static MULTIVALUE_POOL: RefCell>> = const { RefCell::new(Vec::new()) }; +} + /// Multiple Lua values used for both argument passing and also for multiple return values. #[derive(Debug, Clone)] -pub struct MultiValue { - deque: VecDeque, - // FIXME - // lua: Option<&'static Lua>, -} +pub struct MultiValue(VecDeque); impl Drop for MultiValue { fn drop(&mut self) { - // FIXME - // if let Some(lua) = self.lua { - // let vec = mem::take(&mut self.deque); - // lua.push_multivalue_to_pool(vec); - // } + MULTIVALUE_POOL.with_borrow_mut(|pool| { + if pool.len() < MULTIVALUE_POOL_SIZE { + self.0.clear(); + pool.push(mem::take(&mut self.0)); + } + }); } } @@ -774,44 +779,38 @@ impl Deref for MultiValue { #[inline] fn deref(&self) -> &Self::Target { - &self.deque + &self.0 } } impl DerefMut for MultiValue { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.deque + &mut self.0 } } impl MultiValue { /// Creates an empty `MultiValue` containing no values. - pub const fn new() -> MultiValue { - MultiValue { - deque: VecDeque::new(), - // lua: None, - } + pub fn new() -> MultiValue { + Self::with_capacity(0) } /// Similar to `new` but can reuse previously used container with allocated capacity. #[inline] - pub(crate) fn with_lua_and_capacity(_lua: &Lua, capacity: usize) -> MultiValue { - // FIXME - // let deque = lua - // .pop_multivalue_from_pool() - // .map(|mut deque| { - // if capacity > 0 { - // deque.reserve(capacity); - // } - // deque - // }) - // .unwrap_or_else(|| VecDeque::with_capacity(capacity)); - let deque = VecDeque::with_capacity(capacity); - MultiValue { - deque, - // lua: Some(lua), - } + pub(crate) fn with_capacity(capacity: usize) -> MultiValue { + let deque = MULTIVALUE_POOL.with_borrow_mut(|pool| { + pool.pop().map_or_else( + || VecDeque::with_capacity(capacity), + |mut deque| { + if capacity > 0 { + deque.reserve(capacity); + } + deque + }, + ) + }); + MultiValue(deque) } #[inline] @@ -826,11 +825,9 @@ impl MultiValue { impl FromIterator for MultiValue { #[inline] fn from_iter>(iter: I) -> Self { - let deque = VecDeque::from_iter(iter); - MultiValue { - deque, - // lua: None, - } + let mut multi_value = MultiValue::new(); + multi_value.extend(iter); + multi_value } } @@ -840,7 +837,7 @@ impl IntoIterator for MultiValue { #[inline] fn into_iter(mut self) -> Self::IntoIter { - let deque = mem::take(&mut self.deque); + let deque = mem::take(&mut self.0); mem::forget(self); deque.into_iter() } @@ -852,7 +849,7 @@ impl<'a> IntoIterator for &'a MultiValue { #[inline] fn into_iter(self) -> Self::IntoIter { - self.deque.iter() + self.0.iter() } } @@ -910,7 +907,7 @@ pub trait FromLuaMulti: Sized { #[doc(hidden)] #[inline] unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result { - let mut values = MultiValue::with_lua_and_capacity(lua.lua(), nvals as usize); + let mut values = MultiValue::with_capacity(nvals as usize); for idx in 0..nvals { values.push_back(lua.stack_value(-nvals + idx)); }