diff --git a/examples/lots_of_threads.luau b/examples/lots_of_threads.luau new file mode 100644 index 0000000..de8cc87 --- /dev/null +++ b/examples/lots_of_threads.luau @@ -0,0 +1,29 @@ +--!nocheck +--!nolint UnknownGlobal + +local NUM_BATCHES = 100 +local NUM_THREADS = 10_000 + +print(`Spawning {NUM_BATCHES * NUM_THREADS} threads split into {NUM_BATCHES} batches\n`) + +local before = os.clock() +for i = 1, NUM_BATCHES do + print(`Batch {i} of {NUM_BATCHES}`) + local thread = coroutine.running() + + local counter = 0 + for j = 1, NUM_THREADS do + __runtime__spawn(function() + sleep() + counter += 1 + if counter == NUM_THREADS then + __runtime__spawn(thread) + end + end) + end + + coroutine.yield() +end +local after = os.clock() + +print(`\nSpawned {NUM_BATCHES * NUM_THREADS} sleeping threads in {after - before}s`) diff --git a/examples/lots_of_threads.rs b/examples/lots_of_threads.rs new file mode 100644 index 0000000..33e1948 --- /dev/null +++ b/examples/lots_of_threads.rs @@ -0,0 +1,33 @@ +use std::time::Duration; + +use smol_mlua::{ + mlua::prelude::{Lua, LuaResult}, + smol::Timer, + Runtime, +}; + +const MAIN_SCRIPT: &str = include_str!("./lots_of_threads.luau"); + +const ONE_NANOSECOND: Duration = Duration::from_nanos(1); + +pub fn main() -> LuaResult<()> { + // Set up persistent lua environment + let lua = Lua::new(); + lua.globals().set( + "sleep", + lua.create_async_function(|_, ()| async move { + // Obviously we can't sleep for a single nanosecond since + // this uses OS scheduling under the hood, but we can try + Timer::after(ONE_NANOSECOND).await; + Ok(()) + })?, + )?; + + // Load the main script into a runtime and run it until completion + let rt = Runtime::new(&lua)?; + let main = lua.load(MAIN_SCRIPT); + rt.push_thread(&lua, main, ()); + rt.run_blocking(&lua); + + Ok(()) +}