From f63cb7d8345f39582cd42ba1e1ad70506ed3c4e8 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2026 05:15:24 +0000 Subject: [PATCH] Refactor property extraction in web module to use imperative loops Replaced `.iter().find()` calls with `for` loops to extract properties in `stdlib/src/web/renderer.rs` and `stdlib/src/web/db.rs` to avoid closure and iterator overhead. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- .jules/bolt.md | 4 ++ stdlib/src/web/db.rs | 22 ++++---- stdlib/src/web/renderer.rs | 106 +++++++++++++++++-------------------- 3 files changed, 64 insertions(+), 68 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 86371a76..3faa4acb 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -66,3 +66,7 @@ ## 2023-11-09 - Dominator Analysis Optimization **Learning:** In fixed-point iterative algorithms like the dominator tree analysis, using `Option>` and continuously allocating or cloning new sets (`new_dom = Some(pred_doms.clone())`, `all_blocks.clone()`) inside the inner loop is extremely expensive and produces O(N) intermediate allocations per block per iteration. **Action:** Always pre-allocate a single mutable `HashSet` outside the loop, use `.clear()` each iteration, and compute in-place intersections using `.extend()` and `.retain()`. Also, use `.clone_from()` for updates to reuse existing capacity instead of reassignment. + +## 2024-05-24 - Web Property Extraction Optimization +**Learning:** Extracting properties from the `RuntimeValue` DSL property lists in `stdlib/src/web/renderer.rs` and `stdlib/src/web/db.rs` was inefficient because the code called `.iter().find()` to resolve `text`, `id`, and `name` attributes, which creates unnecessary iterator overhead and closure allocation. +**Action:** Replace `.iter().find()` calls with a single-pass `for p in &dsl.properties` loop and `if` statements on the property names, stopping early when found, which significantly reduces execution overhead. diff --git a/stdlib/src/web/db.rs b/stdlib/src/web/db.rs index a9656f50..dce5fcfd 100644 --- a/stdlib/src/web/db.rs +++ b/stdlib/src/web/db.rs @@ -30,18 +30,16 @@ pub fn init_sqlite_database(dsl: &DslBlockValue) { if let Ok(conn) = open_connection() { for child in &dsl.children { if child.kind == "table" { - let table_name = child - .args - .first() - .map(|a| a.to_string()) - .or_else(|| { - child - .properties - .iter() - .find(|p| p.name == "name" || p.name == "id") - .and_then(|p| p.value.as_ref().map(|v| v.to_string())) - }) - .unwrap_or_else(|| "records".to_string()); + let mut table_name = child.args.first().map(|a| a.to_string()); + if table_name.is_none() { + for p in &child.properties { + if p.name == "name" || p.name == "id" { + table_name = p.value.as_ref().map(|v| v.to_string()); + break; + } + } + } + let table_name = table_name.unwrap_or_else(|| "records".to_string()); let clean_name = sanitize_identifier(&table_name); let create_sql = format!( diff --git a/stdlib/src/web/renderer.rs b/stdlib/src/web/renderer.rs index 617a9599..5eb9ba74 100644 --- a/stdlib/src/web/renderer.rs +++ b/stdlib/src/web/renderer.rs @@ -380,17 +380,16 @@ pub fn render_card(html: &mut String, dsl: &DslBlockValue) { pub fn render_heading(html: &mut String, dsl: &DslBlockValue) { let mut id_attr = String::new(); - let text = dsl - .args - .first() - .map(|a| a.to_string()) - .or_else(|| { - dsl.properties - .iter() - .find(|p| p.name == "text") - .and_then(|p| p.value.as_ref().map(|v| v.to_string())) - }) - .unwrap_or_else(|| "Heading".to_string()); + let mut text = dsl.args.first().map(|a| a.to_string()); + if text.is_none() { + for p in &dsl.properties { + if p.name == "text" { + text = p.value.as_ref().map(|v| v.to_string()); + break; + } + } + } + let text = text.unwrap_or_else(|| "Heading".to_string()); for p in &dsl.properties { if p.name == "id" { if let Some(ref v) = p.value { @@ -408,17 +407,16 @@ pub fn render_heading(html: &mut String, dsl: &DslBlockValue) { pub fn render_text(html: &mut String, dsl: &DslBlockValue) { let mut id_attr = String::new(); - let text = dsl - .args - .first() - .map(|a| a.to_string()) - .or_else(|| { - dsl.properties - .iter() - .find(|p| p.name == "text" || p.name == "content") - .and_then(|p| p.value.as_ref().map(|v| v.to_string())) - }) - .unwrap_or_default(); + let mut text = dsl.args.first().map(|a| a.to_string()); + if text.is_none() { + for p in &dsl.properties { + if p.name == "text" || p.name == "content" { + text = p.value.as_ref().map(|v| v.to_string()); + break; + } + } + } + let text = text.unwrap_or_default(); for p in &dsl.properties { if p.name == "id" { if let Some(ref v) = p.value { @@ -1151,17 +1149,16 @@ pub fn render_custom_3d_studio(html: &mut String, _dsl: &DslBlockValue, id: &str } pub fn render_scene3d(html: &mut String, dsl: &DslBlockValue) { - let raw_scene_id = dsl - .args - .first() - .map(|a| a.to_string()) - .or_else(|| { - dsl.properties - .iter() - .find(|p| p.name == "id") - .and_then(|p| p.value.as_ref().map(|v| v.to_string())) - }) - .unwrap_or_else(|| "World".to_string()); + let mut raw_scene_id = dsl.args.first().map(|a| a.to_string()); + if raw_scene_id.is_none() { + for p in &dsl.properties { + if p.name == "id" { + raw_scene_id = p.value.as_ref().map(|v| v.to_string()); + break; + } + } + } + let raw_scene_id = raw_scene_id.unwrap_or_else(|| "World".to_string()); let id = escape_html(&raw_scene_id); let is_custom_studio = raw_scene_id.to_lowercase().contains("custom") @@ -1837,18 +1834,16 @@ pub fn find_database_tables(blocks: &[RuntimeValue]) -> Vec { if dsl.kind == "database" { for child in &dsl.children { if child.kind == "table" { - let name = child - .args - .first() - .map(|a| a.to_string()) - .or_else(|| { - child - .properties - .iter() - .find(|p| p.name == "name" || p.name == "id") - .and_then(|p| p.value.as_ref().map(|v| v.to_string())) - }) - .unwrap_or_else(|| "records".to_string()); + let mut name = child.args.first().map(|a| a.to_string()); + if name.is_none() { + for p in &child.properties { + if p.name == "name" || p.name == "id" { + name = p.value.as_ref().map(|v| v.to_string()); + break; + } + } + } + let name = name.unwrap_or_else(|| "records".to_string()); let clean = db::sanitize_identifier(&name); if !tables.contains(&clean) { tables.push(clean); @@ -2076,17 +2071,16 @@ pub fn render_complete_document( if !scenes_3d.is_empty() { doc.push_str("