Skip to content

Commit bf87db3

Browse files
Merge pull request #290 from Tcode-Motion/bolt/optimize-web-property-extraction-13227510839661946489
⚡ Bolt: Optimize web property extraction
2 parents 5846344 + f63cb7d commit bf87db3

3 files changed

Lines changed: 64 additions & 68 deletions

File tree

‎.jules/bolt.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,7 @@
6666
## 2023-11-09 - Dominator Analysis Optimization
6767
**Learning:** In fixed-point iterative algorithms like the dominator tree analysis, using `Option<HashSet<T>>` 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.
6868
**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.
69+
70+
## 2024-05-24 - Web Property Extraction Optimization
71+
**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.
72+
**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.

‎stdlib/src/web/db.rs‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,16 @@ pub fn init_sqlite_database(dsl: &DslBlockValue) {
3030
if let Ok(conn) = open_connection() {
3131
for child in &dsl.children {
3232
if child.kind == "table" {
33-
let table_name = child
34-
.args
35-
.first()
36-
.map(|a| a.to_string())
37-
.or_else(|| {
38-
child
39-
.properties
40-
.iter()
41-
.find(|p| p.name == "name" || p.name == "id")
42-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
43-
})
44-
.unwrap_or_else(|| "records".to_string());
33+
let mut table_name = child.args.first().map(|a| a.to_string());
34+
if table_name.is_none() {
35+
for p in &child.properties {
36+
if p.name == "name" || p.name == "id" {
37+
table_name = p.value.as_ref().map(|v| v.to_string());
38+
break;
39+
}
40+
}
41+
}
42+
let table_name = table_name.unwrap_or_else(|| "records".to_string());
4543

4644
let clean_name = sanitize_identifier(&table_name);
4745
let create_sql = format!(

‎stdlib/src/web/renderer.rs‎

Lines changed: 50 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -380,17 +380,16 @@ pub fn render_card(html: &mut String, dsl: &DslBlockValue) {
380380

381381
pub fn render_heading(html: &mut String, dsl: &DslBlockValue) {
382382
let mut id_attr = String::new();
383-
let text = dsl
384-
.args
385-
.first()
386-
.map(|a| a.to_string())
387-
.or_else(|| {
388-
dsl.properties
389-
.iter()
390-
.find(|p| p.name == "text")
391-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
392-
})
393-
.unwrap_or_else(|| "Heading".to_string());
383+
let mut text = dsl.args.first().map(|a| a.to_string());
384+
if text.is_none() {
385+
for p in &dsl.properties {
386+
if p.name == "text" {
387+
text = p.value.as_ref().map(|v| v.to_string());
388+
break;
389+
}
390+
}
391+
}
392+
let text = text.unwrap_or_else(|| "Heading".to_string());
394393
for p in &dsl.properties {
395394
if p.name == "id" {
396395
if let Some(ref v) = p.value {
@@ -408,17 +407,16 @@ pub fn render_heading(html: &mut String, dsl: &DslBlockValue) {
408407

409408
pub fn render_text(html: &mut String, dsl: &DslBlockValue) {
410409
let mut id_attr = String::new();
411-
let text = dsl
412-
.args
413-
.first()
414-
.map(|a| a.to_string())
415-
.or_else(|| {
416-
dsl.properties
417-
.iter()
418-
.find(|p| p.name == "text" || p.name == "content")
419-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
420-
})
421-
.unwrap_or_default();
410+
let mut text = dsl.args.first().map(|a| a.to_string());
411+
if text.is_none() {
412+
for p in &dsl.properties {
413+
if p.name == "text" || p.name == "content" {
414+
text = p.value.as_ref().map(|v| v.to_string());
415+
break;
416+
}
417+
}
418+
}
419+
let text = text.unwrap_or_default();
422420
for p in &dsl.properties {
423421
if p.name == "id" {
424422
if let Some(ref v) = p.value {
@@ -1151,17 +1149,16 @@ pub fn render_custom_3d_studio(html: &mut String, _dsl: &DslBlockValue, id: &str
11511149
}
11521150

11531151
pub fn render_scene3d(html: &mut String, dsl: &DslBlockValue) {
1154-
let raw_scene_id = dsl
1155-
.args
1156-
.first()
1157-
.map(|a| a.to_string())
1158-
.or_else(|| {
1159-
dsl.properties
1160-
.iter()
1161-
.find(|p| p.name == "id")
1162-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
1163-
})
1164-
.unwrap_or_else(|| "World".to_string());
1152+
let mut raw_scene_id = dsl.args.first().map(|a| a.to_string());
1153+
if raw_scene_id.is_none() {
1154+
for p in &dsl.properties {
1155+
if p.name == "id" {
1156+
raw_scene_id = p.value.as_ref().map(|v| v.to_string());
1157+
break;
1158+
}
1159+
}
1160+
}
1161+
let raw_scene_id = raw_scene_id.unwrap_or_else(|| "World".to_string());
11651162
let id = escape_html(&raw_scene_id);
11661163

11671164
let is_custom_studio = raw_scene_id.to_lowercase().contains("custom")
@@ -1837,18 +1834,16 @@ pub fn find_database_tables(blocks: &[RuntimeValue]) -> Vec<String> {
18371834
if dsl.kind == "database" {
18381835
for child in &dsl.children {
18391836
if child.kind == "table" {
1840-
let name = child
1841-
.args
1842-
.first()
1843-
.map(|a| a.to_string())
1844-
.or_else(|| {
1845-
child
1846-
.properties
1847-
.iter()
1848-
.find(|p| p.name == "name" || p.name == "id")
1849-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
1850-
})
1851-
.unwrap_or_else(|| "records".to_string());
1837+
let mut name = child.args.first().map(|a| a.to_string());
1838+
if name.is_none() {
1839+
for p in &child.properties {
1840+
if p.name == "name" || p.name == "id" {
1841+
name = p.value.as_ref().map(|v| v.to_string());
1842+
break;
1843+
}
1844+
}
1845+
}
1846+
let name = name.unwrap_or_else(|| "records".to_string());
18521847
let clean = db::sanitize_identifier(&name);
18531848
if !tables.contains(&clean) {
18541849
tables.push(clean);
@@ -2076,17 +2071,16 @@ pub fn render_complete_document(
20762071
if !scenes_3d.is_empty() {
20772072
doc.push_str("<script>document.addEventListener('DOMContentLoaded', () => {");
20782073
for sc in &scenes_3d {
2079-
let sc_id = sc
2080-
.args
2081-
.first()
2082-
.map(|a| a.to_string())
2083-
.or_else(|| {
2084-
sc.properties
2085-
.iter()
2086-
.find(|p| p.name == "id")
2087-
.and_then(|p| p.value.as_ref().map(|v| v.to_string()))
2088-
})
2089-
.unwrap_or_else(|| "World".to_string());
2074+
let mut sc_id = sc.args.first().map(|a| a.to_string());
2075+
if sc_id.is_none() {
2076+
for p in &sc.properties {
2077+
if p.name == "id" {
2078+
sc_id = p.value.as_ref().map(|v| v.to_string());
2079+
break;
2080+
}
2081+
}
2082+
}
2083+
let sc_id = sc_id.unwrap_or_else(|| "World".to_string());
20902084

20912085
let mut initial_geo = "scifi".to_string();
20922086
let mut initial_color = "cyan".to_string();

0 commit comments

Comments
 (0)