diff --git a/.jules/bolt.md b/.jules/bolt.md index 5034e016..fff4cb0a 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -20,3 +20,6 @@ ## 2024-08-01 - Bytecode Disassembler String Allocation Optimization **Learning:** Formatting directly into a string buffer inside a tight loop with `write!(buffer, ...)` avoids unnecessary string heap allocations compared to `buffer.push_str(&format!(...))`. **Action:** Always prefer formatting directly into the target String buffer when concatenating strings in loops in performance-sensitive paths like debuggers or disassemblers. +## 2024-05-24 - Optimize rusqlite extraction in query_map +**Learning:** When mapping `rusqlite` query results to dynamic types like `IndexMap` in `techscript_stdlib`, use `row.get_ref_unwrap(i)` to map the underlying `rusqlite::types::ValueRef` directly to the corresponding `RuntimeValue` (e.g., `Int`, `Float`, `Str`), avoiding the overhead and type issues of coercing all numeric and null columns to `String`s. +**Action:** When extracting data from rusqlite database rows, inspect the `ValueRef` directly with `get_ref` or `get_ref_unwrap` instead of eagerly copying out a target Rust type like `String`, significantly reducing allocations and retaining correct native types for numeric and null data. diff --git a/Cargo.lock b/Cargo.lock index 9077b511..693f55b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4052,7 +4052,7 @@ name = "techscript_package_manager" version = "2.0.0" dependencies = [ "anyhow", - "criterion", + "criterion 0.8.2", "serde", "serde_json", "toml 1.1.4+spec-1.1.0", diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 5f69703d..db29ab73 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -185,7 +185,7 @@ impl StdlibRegistry { .query_map(rusqlite::params_from_iter(params), |row| { let mut map = IndexMap::with_capacity(col_count); for i in 0..col_count { - let val = row.get_ref(i)?; + let val = row.get_ref_unwrap(i); let rt_val = match val { rusqlite::types::ValueRef::Null => RuntimeValue::Null, rusqlite::types::ValueRef::Integer(v) => { @@ -194,11 +194,9 @@ impl StdlibRegistry { rusqlite::types::ValueRef::Real(v) => { RuntimeValue::Float(v) } - rusqlite::types::ValueRef::Text(v) => { - RuntimeValue::Str( - String::from_utf8_lossy(v).into_owned(), - ) - } + rusqlite::types::ValueRef::Text(v) => RuntimeValue::Str( + std::str::from_utf8(v).unwrap_or_default().to_string(), + ), rusqlite::types::ValueRef::Blob(v) => { RuntimeValue::Str( String::from_utf8_lossy(v).into_owned(),