From 62208591fc5a0e0d1f31b28d067960d0993154d9 Mon Sep 17 00:00:00 2001 From: jeangab Date: Thu, 10 Aug 2023 10:55:08 -0400 Subject: [PATCH] Its alive! Refactoring to improve performance using pointers works, now performance still sucks because there is no spatial index and there are some math bugs that create nodes way too far from home --- Cargo.lock | 24 +++++------ Cargo.toml | 2 +- src/app.rs | 2 + src/components/background.rs | 44 +++++++++++++++----- src/routes/empty/mod.rs | 2 + src/routes/empty/page.rs | 12 ++++++ src/routes/mod.rs | 1 + src/space_colonization/mod.rs | 14 +------ src/space_colonization/space_colonization.rs | 18 ++++---- 9 files changed, 74 insertions(+), 45 deletions(-) create mode 100644 src/routes/empty/mod.rs create mode 100644 src/routes/empty/page.rs diff --git a/Cargo.lock b/Cargo.lock index 99cf8c3..53ebaae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2640,9 +2640,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2650,16 +2650,16 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -2677,9 +2677,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2687,22 +2687,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" diff --git a/Cargo.toml b/Cargo.toml index 4f95d55..c50aaa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ leptos_actix = { version = "0.2", optional = true } leptos_router = { version = "0.2", default-features = false } log = "0.4" simple_logger = "4" -wasm-bindgen = "=0.2.84" +wasm-bindgen = "=0.2.87" js-sys = "0.3.51" rand = "0.8.5" getrandom = { version = "0.2", features = ["js"] } diff --git a/src/app.rs b/src/app.rs index 1569139..5a494ca 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,6 +2,7 @@ use crate::components::BackgroundProps; use crate::components::Background; use crate::routes::whymdc::*; use crate::routes::home::*; +use crate::routes::empty::*; use crate::routes::blog::*; use leptos::*; use leptos_meta::*; @@ -35,6 +36,7 @@ pub fn App(cx: Scope) -> impl IntoView { }/> }/> }/> + }/> diff --git a/src/components/background.rs b/src/components/background.rs index 35c171b..a1f8acd 100644 --- a/src/components/background.rs +++ b/src/components/background.rs @@ -1,5 +1,9 @@ +use std::cell::RefCell; +use std::rc::Rc; + use leptos::html::Canvas; use leptos::*; +use wasm_bindgen::prelude::Closure; use wasm_bindgen::JsCast; use wasm_bindgen::JsValue; use web_sys::window; @@ -17,11 +21,16 @@ pub fn Background(cx: Scope, class: &'static str) -> impl IntoView { let canvas_parent = canvas.parent_element().unwrap(); let width = canvas_parent.client_width(); let height = canvas_parent.client_height(); - canvas.set_width(u32::try_from(width).unwrap()); - canvas.set_height(u32::try_from(height).unwrap()); + let window_width = u32::try_from(width).unwrap(); + let window_height = u32::try_from(height).unwrap(); + canvas.set_width(window_width); + canvas.set_height(window_height); let mut sc = SpaceColonization::new(width.try_into().unwrap(), height.try_into().unwrap()); - let mut nodes = Vec::new(); - nodes.push(Node::new(Point::new((100, 100)))); + let nodes = Rc::new(RefCell::new(Vec::new())); + nodes.borrow_mut().push(Node::new(Point::new(( + (window_width / 2) as i32, + (window_height / 2) as i32, + )))); // TODO Resize on window resize log!( "TODO resize on window resize canvas parent size = {} {}", @@ -47,7 +56,7 @@ pub fn Background(cx: Scope, class: &'static str) -> impl IntoView { context.line_to(child.position.x.into(), child.position.y.into()); }; let render_id = window().unwrap().performance().unwrap().now(); - sc.render_nodes(&nodes, render_id, render_node_fn); + sc.render_nodes(&nodes.borrow(), render_id, render_node_fn); context.stroke(); context.set_fill_style(&JsValue::from("magenta")); @@ -60,14 +69,29 @@ pub fn Background(cx: Scope, class: &'static str) -> impl IntoView { sc.attractors.len(), end_time - start_time ); - - for _i in 1..150 { - nodes = sc.grow(nodes); + let context = context.clone(); + let closure = Closure::::new(move |_: web_sys::MouseEvent| { + let start_time = window().unwrap().performance().unwrap().now(); + let render_node_fn = |n: &Node, child: &Node| { + context.move_to(n.position.x.into(), n.position.y.into()); + context.line_to(child.position.x.into(), child.position.y.into()); + }; + sc.grow(&mut nodes.borrow_mut()); let render_id = window().unwrap().performance().unwrap().now(); context.begin_path(); - sc.render_nodes(&nodes, render_id, render_node_fn); + sc.render_nodes(&nodes.borrow(), render_id, render_node_fn); context.stroke(); - } + let end_time = window().unwrap().performance().unwrap().now(); + log!( + "Rendering nodes and {} attractors took {}", + sc.attractors.len(), + end_time - start_time + ); + }); + + let window = window().unwrap(); + window.add_event_listener_with_callback("click", closure.as_ref().unchecked_ref()).unwrap(); + closure.forget(); }); let class = format!("canvas {}", class); diff --git a/src/routes/empty/mod.rs b/src/routes/empty/mod.rs new file mode 100644 index 0000000..f5f67f8 --- /dev/null +++ b/src/routes/empty/mod.rs @@ -0,0 +1,2 @@ +mod page; +pub use page::*; diff --git a/src/routes/empty/page.rs b/src/routes/empty/page.rs new file mode 100644 index 0000000..39dc4bd --- /dev/null +++ b/src/routes/empty/page.rs @@ -0,0 +1,12 @@ +use leptos::*; +use leptos_meta::*; + +/// Renders the home page of your application. +#[component] +pub fn Empty(cx: Scope) -> impl IntoView { + view! { cx, + + <div class=""> + </div> + } +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 1bfe892..22d4b35 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,3 +1,4 @@ pub mod whymdc; pub mod home; pub mod blog; +pub mod empty; diff --git a/src/space_colonization/mod.rs b/src/space_colonization/mod.rs index dbce4f0..b10e132 100644 --- a/src/space_colonization/mod.rs +++ b/src/space_colonization/mod.rs @@ -19,9 +19,9 @@ pub struct Attractor { } impl Attractor { - pub fn new(position: (i32, i32)) -> Attractor { + pub fn new(position: Point) -> Attractor { Attractor { - position: Point::new(position), + position, dead: false, } } @@ -55,16 +55,6 @@ impl Attraction { } } -#[derive(Debug)] -pub struct NodeRef { - path: Vec<u16>, -} - -#[derive(Debug)] -pub struct AttractorRef { - path: Vec<u16>, -} - impl std::hash::Hash for Node { fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.position.hash(state); diff --git a/src/space_colonization/space_colonization.rs b/src/space_colonization/space_colonization.rs index 0b9fcae..5a776ed 100644 --- a/src/space_colonization/space_colonization.rs +++ b/src/space_colonization/space_colonization.rs @@ -95,10 +95,9 @@ impl SpaceColonization { let mut y_pos = 0; while x_pos < self.max_point.x { while y_pos < self.max_point.y { - self.attractors.push(Attractor { - position: self.get_random_point(x_pos.into(), y_pos.into()), - dead: false, - }); + self.attractors.push(Attractor::new( + self.get_random_point(x_pos.into(), y_pos.into()), + )); y_pos += self.density; } x_pos += self.density; @@ -130,7 +129,7 @@ impl SpaceColonization { } } - pub fn grow(&mut self, mut nodes: Vec<Node>) -> Vec<Node> { + pub fn grow<'a>(&mut self, mut nodes: &'a mut Vec<Node>) { // TODO // [x] Find a clean API that will be stable across refactoring // [ ] Write the test against this api including performance @@ -140,8 +139,7 @@ impl SpaceColonization { // - I can efficiently render my nodes on a canvas // - I use as little memory as possible // - I can update my nodes - self.grow_nodes(&mut nodes); - nodes + self.grow_nodes(&mut nodes) } pub fn grow_nodes(&mut self, nodes: &mut Vec<Node>) { @@ -287,7 +285,7 @@ mod test { let mut nodes = Vec::new(); nodes.push(Node::new(Point::new((0, 0)))); let mut attractors = Vec::new(); - attractors.push(Attractor::new((10, 0))); + attractors.push(Attractor::new(Point::new((10, 0)))); let mut sc = SpaceColonization::new_for_tests(100, 100, attractors); @@ -296,13 +294,13 @@ mod test { println!("before grow"); dbg!(&nodes); - nodes = sc.grow(nodes); + sc.grow(&mut nodes); println!("after grow 1"); dbg!(&nodes); assert!(sc.attractors.iter().find(|a| a.dead == true).is_none()); - nodes = sc.grow(nodes); + sc.grow(&mut nodes); println!("after grow 2"); dbg!(&nodes);