Skip to content

Add Lua::(reset_)num_allocations API #314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ pub enum Error {
GarbageCollectorError(StdString),
/// Potentially unsafe action in safe mode.
SafetyError(StdString),
/// Setting memory limit is not available.
/// Setting memory limit or getting/resetting the number of allocation is not available.
///
/// This error can only happen when Lua state was not created by us and does not have the
/// custom allocator attached.
MemoryLimitNotAvailable,
MemoryStatsNotAvailable,
/// A mutable callback has triggered Lua code that has called the same mutable callback again.
///
/// This is an error because a mutable callback can only be borrowed mutably once.
Expand Down Expand Up @@ -218,8 +218,8 @@ impl fmt::Display for Error {
Error::SafetyError(ref msg) => {
write!(fmt, "safety error: {msg}")
},
Error::MemoryLimitNotAvailable => {
write!(fmt, "setting memory limit is not available")
Error::MemoryStatsNotAvailable => {
write!(fmt, "memory stats information is not available")
}
Error::RecursiveMutCallback => write!(fmt, "mutable callback called recursively"),
Error::CallbackDestructed => write!(
Expand Down
32 changes: 31 additions & 1 deletion src/lua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,37 @@ impl Lua {
unsafe {
match (*self.extra.get()).mem_state.map(|mut x| x.as_mut()) {
Some(mem_state) => Ok(mem_state.set_memory_limit(limit)),
None => Err(Error::MemoryLimitNotAvailable),
None => Err(Error::MemoryStatsNotAvailable),
}
}
}

/// Returns the count of memory allocations invoked by this Lua runtime.
///
/// Note that in case of overflow, the counter resets to zero(simply speaking, it 'wraps'),
/// and the overflowing threshold above the maximum depends on the platform.
///
/// Returns [`Error::MemoryStatsNotAvailable`] if Lua state is managed externally.
pub fn num_allocations(&self) -> Result<usize> {
unsafe {
match (*self.extra.get()).mem_state.map(|x| x.as_ref()) {
Some(mem_state) => Ok(mem_state.num_allocations()),
None => Err(Error::MemoryStatsNotAvailable),
}
}
}

/// Resets the count of memory allocations to zero.
///
/// Returns [`Error::MemoryStatsNotAvailable`] if Lua state is managed externally.
pub fn reset_num_allocations(&self) -> Result<()> {
unsafe {
match (*self.extra.get()).mem_state.map(|mut x| x.as_mut()) {
Some(mem_state) => {
mem_state.reset_num_allocations();
Ok(())
}
None => Err(Error::MemoryStatsNotAvailable),
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) struct MemoryState {
// Indicates that the memory limit was reached on the last allocation.
#[cfg(feature = "luau")]
limit_reached: bool,
num_allocations: usize,
}

impl MemoryState {
Expand All @@ -37,6 +38,16 @@ impl MemoryState {
prev_limit as usize
}

#[inline]
pub(crate) fn num_allocations(&self) -> usize {
self.num_allocations
}

#[inline]
pub(crate) fn reset_num_allocations(&mut self) {
self.num_allocations = 0;
}

// This function is used primarily for calling `lua_pushcfunction` in lua5.1/jit
// to bypass the memory limit (if set).
#[cfg(any(feature = "lua51", feature = "luajit"))]
Expand Down Expand Up @@ -139,6 +150,7 @@ unsafe extern "C-unwind" fn allocator(
if new_ptr.is_null() {
alloc::handle_alloc_error(new_layout);
}
mem_state.num_allocations = mem_state.num_allocations.wrapping_add(1);
return new_ptr;
}

Expand Down