From 73ffbee638c03da132aea0e5d600ca5e8144fd8e Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 3 Jul 2026 15:33:08 -0400 Subject: Support WASM, kinda --- src/main.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 81fffcf..7c4f249 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,22 +7,21 @@ use tortuise::{ file::FileManager, input::InputManager, scene::switch_scenes, - script::{ScriptContext, ScriptDeclaration, ScriptManager}, + script::{ScriptContext, ScriptDeclaration, ScriptManager, WasmRunner}, }; #[global_allocator] static GLOBAL: MiMalloc = MiMalloc; fn get_timestamp() -> u128 { - SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos() + SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros() } -fn init_first_frame<'a>(_: &mut ScriptContext<'a>, state: &mut Box<[u8]>) { +fn init_first_frame(_: &mut ScriptContext, state: &mut Box<[u8]>) { *state = Box::from(get_timestamp().to_ne_bytes()); } -fn render_frame_rate<'a>(ctx: &mut ScriptContext<'a>, state: &mut Box<[u8]>) { - ctx.buffer.cells.clear(); +fn render_frame_rate(ctx: &mut ScriptContext, state: &mut Box<[u8]>) { let end = get_timestamp(); let last_frame_start = u128::from_ne_bytes(*state.as_array().unwrap()); let frame_time = end - last_frame_start + 1; @@ -53,6 +52,14 @@ fn exit_on_escape(ctx: &mut ScriptContext, _: &mut Box<[u8]>) { } fn main() { + let mut files = FileManager::default(); + let wasm_runner = WasmRunner::new(); + let manifest = files + .load_file(Box::from("manifest.toml".as_ref()), &wasm_runner.engine) + .unwrap() + .unwrap_manifest() + .clone(); + let stdout = Box::new(std::io::stdout().lock()); let mut buffer = Buffer::new(stdout).unwrap(); let mut input = InputManager::new(); @@ -60,6 +67,7 @@ fn main() { buffer: &mut buffer, input: &input, }; + let scripts = [ ScriptDeclaration::Static { start: Some(init_first_frame), @@ -74,17 +82,12 @@ fn main() { ]; let mut scripts = ScriptManager::new(&scripts); - let mut files = FileManager::default(); - let manifest = files - .load_file(Box::from("manifest.toml".as_ref())) - .unwrap() - .unwrap_manifest() - .clone(); switch_scenes( &manifest.scenes, &mut scripts, &mut context, &mut files, + &wasm_runner, manifest.first_scene, ); @@ -100,7 +103,7 @@ fn main() { buffer, input: &input, }; - scripts.run_scripts(&mut context); + scripts.run_scripts(&mut context, &wasm_runner, &mut files); input.reset_next_frame(); } }) -- cgit v1.2.3 From e8fe3415e86e18ac97216ada94002d0a03ee3c8a Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 3 Jul 2026 16:17:35 -0400 Subject: Profiling --- Cargo.lock | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/buffer.rs | 1 + src/input.rs | 1 + src/main.rs | 8 +++++++- src/script.rs | 1 + 6 files changed, 64 insertions(+), 1 deletion(-) (limited to 'src/main.rs') diff --git a/Cargo.lock b/Cargo.lock index 78081df..6947618 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,12 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + [[package]] name = "arbitrary" version = "1.4.2" @@ -193,6 +199,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -1141,6 +1156,12 @@ version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +[[package]] +name = "lz4_flex" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e" + [[package]] name = "mach2" version = "0.4.3" @@ -1440,6 +1461,35 @@ dependencies = [ "syn", ] +[[package]] +name = "puffin" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b514d95a258be801fde8a1ff1c974f4a4841d9750f5d1d6690fc07a5ad4049" +dependencies = [ + "anyhow", + "bincode", + "byteorder", + "cfg-if", + "itertools 0.14.0", + "lz4_flex", + "parking_lot", + "serde", +] + +[[package]] +name = "puffin_http" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f912991aab1adae69d2be9455e8db0f41e5ad3da87706ab2de64908678c2c76" +dependencies = [ + "anyhow", + "crossbeam-channel", + "log", + "parking_lot", + "puffin", +] + [[package]] name = "quote" version = "1.0.45" @@ -1964,6 +2014,8 @@ dependencies = [ "getrandom", "mimalloc", "postcard", + "puffin", + "puffin_http", "rustc-hash", "serde", "smol", diff --git a/Cargo.toml b/Cargo.toml index a13d8c4..fabf7d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ crossterm = "0.29" getrandom = "0.4" mimalloc = "0.1" postcard = "1" +puffin = "0.20" +puffin_http = "0.17" rustc-hash = "2" serde = { version = "1", features = ["derive"] } smol = "2" diff --git a/src/buffer.rs b/src/buffer.rs index 9e91ae7..999a32c 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -59,6 +59,7 @@ impl Buffer { } fn render(&mut self) -> std::io::Result<()> { + puffin::profile_function!(); self.cells.sort_unstable_by_key(|cell| cell.z); queue!(self.stdout, BeginSynchronizedUpdate, Clear(ClearType::All))?; for cell in &self.cells { diff --git a/src/input.rs b/src/input.rs index c86daf4..90ddbb2 100644 --- a/src/input.rs +++ b/src/input.rs @@ -18,6 +18,7 @@ impl InputManager { } pub fn reset_next_frame(&mut self) { + puffin::profile_function!(); self.pressed_keys.clear(); } diff --git a/src/main.rs b/src/main.rs index 7c4f249..1a62ca2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ use tortuise::{ static GLOBAL: MiMalloc = MiMalloc; fn get_timestamp() -> u128 { - SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros() + SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos() } fn init_first_frame(_: &mut ScriptContext, state: &mut Box<[u8]>) { @@ -22,6 +22,7 @@ fn init_first_frame(_: &mut ScriptContext, state: &mut Box<[u8]>) { } fn render_frame_rate(ctx: &mut ScriptContext, state: &mut Box<[u8]>) { + puffin::profile_function!(); let end = get_timestamp(); let last_frame_start = u128::from_ne_bytes(*state.as_array().unwrap()); let frame_time = end - last_frame_start + 1; @@ -46,6 +47,7 @@ fn render_frame_rate(ctx: &mut ScriptContext, state: &mut Box<[u8]>) { } fn exit_on_escape(ctx: &mut ScriptContext, _: &mut Box<[u8]>) { + puffin::profile_function!(); if ctx.input.is_key_pressed_this_frame(KeyCode::Esc) { ctx.exit(); } @@ -91,6 +93,9 @@ fn main() { manifest.first_scene, ); + let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); + let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); + puffin::set_scopes_on(true); buffer .render_loop(|buffer, event| match event { Event::Key(event) => { @@ -105,6 +110,7 @@ fn main() { }; scripts.run_scripts(&mut context, &wasm_runner, &mut files); input.reset_next_frame(); + puffin::GlobalProfiler::lock().new_frame(); } }) .unwrap(); diff --git a/src/script.rs b/src/script.rs index e1634a6..861f665 100644 --- a/src/script.rs +++ b/src/script.rs @@ -162,6 +162,7 @@ impl<'a> ScriptManager<'a> { wasm_runner: &WasmRunner, files: &mut FileManager, ) { + puffin::profile_function!(); for script_id in &self.active_scripts { let Some(script) = self.scripts.get(*script_id) else { unreachable!("The active script does not exist"); -- cgit v1.2.3 From cbbe1ca7f7b36b03e813fbf7e0147341090762bb Mon Sep 17 00:00:00 2001 From: Mica White Date: Fri, 3 Jul 2026 16:32:26 -0400 Subject: Fix performance --- src/buffer.rs | 27 ++++++++++++++++++--------- src/main.rs | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src/main.rs') diff --git a/src/buffer.rs b/src/buffer.rs index 999a32c..6d983db 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -60,16 +60,23 @@ impl Buffer { fn render(&mut self) -> std::io::Result<()> { puffin::profile_function!(); - self.cells.sort_unstable_by_key(|cell| cell.z); - queue!(self.stdout, BeginSynchronizedUpdate, Clear(ClearType::All))?; - for cell in &self.cells { - queue!( - self.stdout, - MoveTo(cell.x, cell.y), - PrintStyledContent(StyledContent::new(cell.style, cell.character)) - )?; + { + puffin::profile_scope!("sort cells"); + self.cells.sort_unstable_by_key(|cell| cell.z); } - queue!(self.stdout, EndSynchronizedUpdate)?; + { + puffin::profile_scope!("queue"); + queue!(self.stdout, BeginSynchronizedUpdate, Clear(ClearType::All))?; + for cell in &self.cells { + queue!( + self.stdout, + MoveTo(cell.x, cell.y), + PrintStyledContent(StyledContent::new(cell.style, cell.character)) + )?; + } + queue!(self.stdout, EndSynchronizedUpdate)?; + } + puffin::profile_scope!("flush"); self.stdout.flush()?; Ok(()) } @@ -96,6 +103,7 @@ impl Buffer { } }); loop { + puffin::profile_scope!("frame"); while let Ok(event) = receiver.try_recv() { if let Ok(event) = event.try_into() { event_handler(self, event); @@ -103,6 +111,7 @@ impl Buffer { } event_handler(self, Event::Render); self.render()?; + puffin::GlobalProfiler::lock().new_frame(); } })?; self.finish()?; diff --git a/src/main.rs b/src/main.rs index 1a62ca2..baea403 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,6 +34,7 @@ fn render_frame_rate(ctx: &mut ScriptContext, state: &mut Box<[u8]>) { frame_time % 100 / 10, frame_time % 10, ]; + ctx.buffer.cells.clear(); for (x, digit) in digits.into_iter().enumerate() { ctx.buffer.cells.push(Cell { character: char::from_digit(digit as u32, 10).unwrap(), @@ -110,7 +111,6 @@ fn main() { }; scripts.run_scripts(&mut context, &wasm_runner, &mut files); input.reset_next_frame(); - puffin::GlobalProfiler::lock().new_frame(); } }) .unwrap(); -- cgit v1.2.3