Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
## 2026-04-08 - [Performance: Defer Allocation during Traversal]
**Learning:** During DAG traversals, creating owned variants of identifiers (like `file.to_path_buf()`) *before* checking `visited` HashSets results in heap allocations (O(E)) for every edge instead of every visited node (O(V)). By moving the `&PathBuf` allocation strictly *after* all HashSet `contains` checks using the borrowed reference (`&Path`), we drastically reduce memory churn.
**Action:** Always check `HashSet::contains` with a borrowed reference *before* creating the owned version required by `HashSet::insert`, especially in performance-critical graph traversal paths.

## 2026-04-09 - [Performance: Dynamic SQL Generation]
**Learning:** For dynamic SQL generation (e.g., in `crates/flow/src/targets/d1.rs` for Cloudflare D1 targets), constructing queries using intermediate `Vec` allocations and joining strings with `format!` causes unnecessary heap allocations and string copies.
**Action:** Always use `String::with_capacity` and the `write!` macro (via `std::fmt::Write`) to construct queries directly to minimize memory allocations and improve query building throughput.
67 changes: 39 additions & 28 deletions crates/flow/src/targets/d1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,40 +300,50 @@ impl D1ExportContext {
key: &KeyValue,
values: &FieldValues,
) -> Result<(String, Vec<serde_json::Value>), RecocoError> {
let mut columns = vec![];
let mut placeholders = vec![];
let mut params = vec![];
let mut update_clauses = vec![];
use std::fmt::Write;
// Bolt optimization: Pre-allocate capacity and avoid intermediate vectors/formats
let mut params = Vec::with_capacity(key.0.len() + values.fields.len());
let mut sql = String::with_capacity(128 + self.table_name.len());

write!(sql, "INSERT INTO {} (", self.table_name).unwrap();

let mut first = true;

// Extract key parts - KeyValue is a wrapper around Box<[KeyPart]>
for (idx, _key_field) in self.key_fields_schema.iter().enumerate() {
if let Some(key_part) = key.0.get(idx) {
columns.push(self.key_fields_schema[idx].name.clone());
placeholders.push("?".to_string());
if !first { sql.push_str(", "); }
sql.push_str(&self.key_fields_schema[idx].name);
params.push(key_part_to_json(key_part)?);
first = false;
}
}

// Add value fields
for (idx, value) in values.fields.iter().enumerate() {
if let Some(value_field) = self.value_fields_schema.get(idx) {
columns.push(value_field.name.clone());
placeholders.push("?".to_string());
if !first { sql.push_str(", "); }
sql.push_str(&value_field.name);
params.push(value_to_json(value)?);
update_clauses.push(format!(
"{} = excluded.{}",
value_field.name, value_field.name
));
first = false;
}
}

let sql = format!(
"INSERT INTO {} ({}) VALUES ({}) ON CONFLICT DO UPDATE SET {}",
self.table_name,
columns.join(", "),
placeholders.join(", "),
update_clauses.join(", ")
);
sql.push_str(") VALUES (");
for i in 0..params.len() {
if i > 0 { sql.push_str(", "); }
sql.push('?');
}

sql.push_str(") ON CONFLICT DO UPDATE SET ");
first = true;
for (idx, _value) in values.fields.iter().enumerate() {
if let Some(value_field) = self.value_fields_schema.get(idx) {
if !first { sql.push_str(", "); }
write!(sql, "{0} = excluded.{0}", value_field.name).unwrap();
first = false;
}
}

Ok((sql, params))
}
Expand All @@ -342,22 +352,23 @@ impl D1ExportContext {
&self,
key: &KeyValue,
) -> Result<(String, Vec<serde_json::Value>), RecocoError> {
let mut where_clauses = vec![];
let mut params = vec![];
use std::fmt::Write;
// Bolt optimization: Pre-allocate capacity and avoid intermediate vectors/formats
let mut params = Vec::with_capacity(key.0.len());
let mut sql = String::with_capacity(64 + self.table_name.len());
write!(sql, "DELETE FROM {} WHERE ", self.table_name).unwrap();

let mut first = true;

for (idx, _key_field) in self.key_fields_schema.iter().enumerate() {
if let Some(key_part) = key.0.get(idx) {
where_clauses.push(format!("{} = ?", self.key_fields_schema[idx].name));
if !first { sql.push_str(" AND "); }
write!(sql, "{} = ?", self.key_fields_schema[idx].name).unwrap();
params.push(key_part_to_json(key_part)?);
first = false;
}
}

let sql = format!(
"DELETE FROM {} WHERE {}",
self.table_name,
where_clauses.join(" AND ")
);

Ok((sql, params))
}

Expand Down