Skip to content
This repository was archived by the owner on Jun 16, 2026. It is now read-only.
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.

## 2024-05-30 - [Performance: Direct String Writing over Format]
**Learning:** Constructing complex SQL queries (or other long strings) with dynamic elements using `format!` or joining intermediate arrays causes multiple unnecessary heap allocations. This directly negatively impacts query generation latency, which can be the bottleneck in the pipeline.
**Action:** For string construction with loops or multiple elements, always use `std::fmt::Write` (the `write!` macro) into a `String::with_capacity(...)` pre-allocated buffer to drastically reduce heap allocations and memory copies.
87 changes: 58 additions & 29 deletions crates/flow/src/targets/d1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,13 @@ impl D1ExportContext {

// Generate cache key from SQL + params
#[cfg(feature = "caching")]
let cache_key = format!("{}{:?}", sql, params);
let cache_key = {
use std::fmt::Write;
let mut key = String::with_capacity(sql.len() + params.len() * 32);
key.push_str(sql);
let _ = write!(key, "{:?}", params);
key
};

// Check cache first (only for caching feature)
#[cfg(feature = "caching")]
Expand Down Expand Up @@ -300,40 +306,60 @@ 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 use write! to construct SQL
// string without intermediate Vec allocations or format! loops
let num_keys = self.key_fields_schema.len();
let num_values = self.value_fields_schema.len();
let mut sql = String::with_capacity(128 + num_keys * 10 + num_values * 30);
let mut params = Vec::with_capacity(num_keys + num_values);

let _ = write!(sql, "INSERT INTO {} (", self.table_name);
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 {
let _ = write!(sql, ", ");
}
let _ = write!(sql, "{}", self.key_fields_schema[idx].name);
first = false;
params.push(key_part_to_json(key_part)?);
}
}

// 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 {
let _ = write!(sql, ", ");
}
let _ = write!(sql, "{}", value_field.name);
first = false;
params.push(value_to_json(value)?);
update_clauses.push(format!(
"{} = excluded.{}",
value_field.name, value_field.name
));
}
}

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

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

Ok((sql, params))
}
Expand All @@ -342,22 +368,25 @@ 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;
let num_keys = self.key_fields_schema.len();
let mut sql = String::with_capacity(32 + self.table_name.len() + num_keys * 20);
let mut params = Vec::with_capacity(num_keys);

let _ = write!(sql, "DELETE FROM {} WHERE ", self.table_name);
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 {
let _ = write!(sql, " AND ");
}
let _ = write!(sql, "{} = ?", self.key_fields_schema[idx].name);
first = false;
params.push(key_part_to_json(key_part)?);
}
}

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

Ok((sql, params))
}

Expand Down