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-24 - Dynamic SQL Generation Optimization
**Learning:** For dynamic SQL generation (e.g., in `crates/flow/src/targets/d1.rs` for Cloudflare D1 targets), using intermediate `Vec` allocations and `format!` in loops is a significant performance bottleneck due to excessive 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 heap allocations and string copies.
104 changes: 72 additions & 32 deletions crates/flow/src/targets/d1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,40 +300,75 @@ 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;

let mut params =
Vec::with_capacity(self.key_fields_schema.len() + self.value_fields_schema.len());

// Pre-calculate string capacity to avoid reallocations
// "INSERT INTO " (12) + table_name + " (" (2) + columns + ") VALUES (" (10) + placeholders + ") ON CONFLICT DO UPDATE SET " (28) + update_clauses
let estimated_len = 12
+ self.table_name.len()
+ 2
+ (self.key_fields_schema.len() + self.value_fields_schema.len()) * 15
+ 10
+ (self.key_fields_schema.len() + self.value_fields_schema.len()) * 3
+ 28
+ self.value_fields_schema.len() * 25;
let mut sql = String::with_capacity(estimated_len);

// Extract key parts - KeyValue is a wrapper around Box<[KeyPart]>
for (idx, _key_field) in self.key_fields_schema.iter().enumerate() {
let _ = write!(sql, "INSERT INTO {} (", self.table_name);

let mut first = true;

// Extract key parts
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, "{}", key_field.name);
first = false;
params.push(key_part_to_json(key_part)?);
}
}

// Add value fields
// Add value fields for columns
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 (");

// Placeholders
for i in 0..params.len() {
if i > 0 {
let _ = write!(sql, ", ?");
} else {
let _ = write!(sql, "?");
}
}

let _ = write!(sql, ") ON CONFLICT DO UPDATE SET ");

// Update clauses
first = true;
for (idx, _value) in values.fields.iter().enumerate() {
if let Some(value_field) = self.value_fields_schema.get(idx) {
if !first {
let _ = write!(sql, ", ");
}
let _ = write!(sql, "{name} = excluded.{name}", name = value_field.name);
first = false;
}
}

Ok((sql, params))
}
Expand All @@ -342,22 +377,27 @@ 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 mut params = Vec::with_capacity(self.key_fields_schema.len());

for (idx, _key_field) in self.key_fields_schema.iter().enumerate() {
let estimated_len = 12 + self.table_name.len() + 7 + self.key_fields_schema.len() * 20;
let mut sql = String::with_capacity(estimated_len);

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, "{} = ?", key_field.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