perf: completely eradicate large vector allocations and state locking double-clones in main, meta, env, workspaces, and notes modules

This commit is contained in:
Riz Ashraf committed 2026-09-21 15:22:44 +01:00
1 parent 6b37799cc5
commit 9476bcd649
9 files changed
+335 -108

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
import os
def fix_env_and_workspaces():
filepath = 'server/src/handlers_v2/env.rs'
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
old_env = """ let fps = state.env_fingerprints.read();
if let Some(fp) = fps.get(&req.namespace) {"""
new_env = """ let data = state.env_fingerprints.read_with(|fps| {
fps.get(&req.namespace).cloned()
});
if let Some(fp) = data {"""
if old_env in content:
content = content.replace(old_env, new_env)
print('Replaced env read')
else:
print('Could not find old_env')
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
filepath = 'server/src/handlers_v2/workspaces.rs'
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
old_ws = """ let query = req.query.to_lowercase();
let snippets = state.snippets.read();
let mut results = Vec::new();
for s in snippets {
if contains_ignore_ascii_case(&s.name, &query)
|| contains_ignore_ascii_case(&s.description, &query)
|| contains_ignore_ascii_case(&s.language, &query)
{
results.push(s);
}
}
let data = serde_json::to_string(&results).unwrap_or_default();"""
new_ws = """ let query = req.query.to_lowercase();
let data = state.snippets.read_with(|snippets| {
let results: Vec<_> = snippets.iter().filter(|s| {
contains_ignore_ascii_case(&s.name, &query)
|| contains_ignore_ascii_case(&s.description, &query)
|| contains_ignore_ascii_case(&s.language, &query)
}).cloned().collect();
serde_json::to_string(&results).unwrap_or_default()
});"""
if old_ws in content:
content = content.replace(old_ws, new_ws)
print('Replaced workspaces read')
else:
print('Could not find old_ws')
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
fix_env_and_workspaces()
+60
View File
@@ -0,0 +1,60 @@
import os
def fix_main_stats():
filepath = 'server/src/main.rs'
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
old_stats = """ let (entities, relations) = {
let graph = state_clone.get_full_graph();
(graph.entities.len(), graph.relations.len())
};
let tasks = state_clone.tasks.read().len();
let snippets = state_clone.snippets.read().len();
let tech_debts = state_clone.tech_debts.read().len();
let adrs = state_clone.adrs.read().len();
let ledger = state_clone.ledger.read().len();
let sticky = state_clone.sticky.read().len();
let error_fixes = state_clone.error_fixes.read().len();
let pinned_files = state_clone.pinned_files.read().len();
let session_summaries = state_clone.session_summaries.read().len();
let handoff_memos = state_clone.handoff_memos.read().len();
let env_fingerprints = state_clone.env_fingerprints.read().len();
let env_requirements = state_clone.env_requirements.read().len();
let milestones = state_clone.milestones.read().len();
let environments = state_clone.environments.read().len();
let pr_checklists = state_clone.pr_checklists.read().len();
let gates = state_clone.gates.read().len();
let context_workspaces = state_clone.context_workspaces.read().len();"""
new_stats = """ let (entities, relations) = state_clone.read_graph(|g| (g.entities.len(), g.relations.len()));
let tasks = state_clone.tasks.read_with(|items| items.len());
let snippets = state_clone.snippets.read_with(|items| items.len());
let tech_debts = state_clone.tech_debts.read_with(|items| items.len());
let adrs = state_clone.adrs.read_with(|items| items.len());
let ledger = state_clone.ledger.read_with(|items| items.len());
let sticky = state_clone.sticky.read_with(|items| items.len());
let error_fixes = state_clone.error_fixes.read_with(|items| items.len());
let pinned_files = state_clone.pinned_files.read_with(|items| items.len());
let session_summaries = state_clone.session_summaries.read_with(|items| items.len());
let handoff_memos = state_clone.handoff_memos.read_with(|items| items.len());
let env_fingerprints = state_clone.env_fingerprints.read_with(|items| items.len());
let env_requirements = state_clone.env_requirements.read_with(|items| items.len());
let milestones = state_clone.milestones.read_with(|items| items.len());
let environments = state_clone.environments.read_with(|items| items.len());
let pr_checklists = state_clone.pr_checklists.read_with(|items| items.len());
let gates = state_clone.gates.read_with(|items| items.len());
let context_workspaces = state_clone.context_workspaces.read_with(|items| items.len());"""
if old_stats in content:
content = content.replace(old_stats, new_stats)
print('Replaced stats reads')
else:
print('Could not find old_stats')
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
fix_main_stats()
+111
View File
@@ -0,0 +1,111 @@
import os
def fix_meta():
filepath = 'server/src/handlers_v2/meta.rs'
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
old_omni = """ let q = req.query.to_lowercase();
let tech_debts: Vec<_> = state
.tech_debts
.read()
.into_iter()
.filter(|d| {
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
&& (contains_ignore_ascii_case(&d.description, &q)
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
})
.collect();
let memos: Vec<_> = state
.handoff_memos
.read()
.into_iter()
.filter(|m| {
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
&& contains_ignore_ascii_case(&m.content, &q)
})
.collect();
let error_fixes: Vec<_> = state
.error_fixes
.read()
.into_iter()
.filter(|f| {
contains_ignore_ascii_case(&f.signature, &q)
|| contains_ignore_ascii_case(&f.solution, &q)
})
.collect();"""
new_omni = """ let q = req.query.to_lowercase();
let tech_debts = state.tech_debts.read_with(|debts| {
debts.iter().filter(|d| {
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
&& (contains_ignore_ascii_case(&d.description, &q)
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
}).cloned().collect::<Vec<_>>()
});
let memos = state.handoff_memos.read_with(|memos| {
memos.iter().filter(|m| {
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
&& contains_ignore_ascii_case(&m.content, &q)
}).cloned().collect::<Vec<_>>()
});
let error_fixes = state.error_fixes.read_with(|fixes| {
fixes.iter().filter(|f| {
contains_ignore_ascii_case(&f.signature, &q)
|| contains_ignore_ascii_case(&f.solution, &q)
}).cloned().collect::<Vec<_>>()
});"""
if old_omni in content:
content = content.replace(old_omni, new_omni)
print('Replaced omni_search vecs')
else:
print('Could not find old_omni')
old_health = """ let active_tasks = state
.tasks
.read()
.into_iter()
.filter(|t| t.status != "done")
.count();
let unresolved_debt = state
.tech_debts
.read()
.into_iter()
.filter(|d| d.namespace == req.namespace && !d.is_resolved)
.count();
let unread_memos = state
.handoff_memos
.read()
.into_iter()
.filter(|m| m.namespace == req.namespace)
.count();
let active_milestones = state
.milestones
.read()
.into_iter()
.filter(|m| m.namespace == req.namespace && m.status != "done")
.count();
let remaining_checklists = state
.pr_checklists
.read()
.into_iter()
.filter(|c| c.namespace == req.namespace)
.count();"""
new_health = """ let active_tasks = state.tasks.read_with(|tasks| tasks.iter().filter(|t| t.status != "done").count());
let unresolved_debt = state.tech_debts.read_with(|debts| debts.iter().filter(|d| d.namespace == req.namespace && !d.is_resolved).count());
let unread_memos = state.handoff_memos.read_with(|memos| memos.iter().filter(|m| m.namespace == req.namespace).count());
let active_milestones = state.milestones.read_with(|milestones| milestones.iter().filter(|m| m.namespace == req.namespace && m.status != "done").count());
let remaining_checklists = state.pr_checklists.read_with(|checklists| checklists.iter().filter(|c| c.namespace == req.namespace).count());"""
if old_health in content:
content = content.replace(old_health, new_health)
print('Replaced health counters')
else:
print('Could not find old_health')
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
fix_meta()
+40
View File
@@ -0,0 +1,40 @@
import os
def fix_notes():
filepath = 'server/src/handlers_v2/notes.rs'
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
old_standup = """ let tasks = state
.tasks
.read()
.into_iter()
.filter(|t| t.updated_at >= cutoff)
.collect::<Vec<_>>();
let changes = state
.ledger
.read()
.into_iter()
.filter(|c| c.timestamp >= cutoff)
.collect::<Vec<_>>();
let summaries = state
.session_summaries
.read()
.into_iter()
.filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff)
.collect::<Vec<_>>();"""
new_standup = """ let tasks = state.tasks.read_with(|items| items.iter().filter(|t| t.updated_at >= cutoff).cloned().collect::<Vec<_>>());
let changes = state.ledger.read_with(|items| items.iter().filter(|c| c.timestamp >= cutoff).cloned().collect::<Vec<_>>());
let summaries = state.session_summaries.read_with(|items| items.iter().filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff).cloned().collect::<Vec<_>>());"""
if old_standup in content:
content = content.replace(old_standup, new_standup)
print('Replaced standup in notes.rs')
else:
print('Could not find old_standup in notes.rs')
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
fix_notes()
+6 -3
View File
@@ -61,9 +61,11 @@ impl McpTool for ReadEnvFingerprintHandler {
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
let req: ReadEnvFingerprintTool =
serde_json::from_value(args).map_err(|e| e.to_string())?;
let fps = state.env_fingerprints.read();
if let Some(fp) = fps.get(&req.namespace) {
let data = serde_json::to_string(fp).unwrap_or_default();
let data = state.env_fingerprints.read_with(|fps| {
fps.get(&req.namespace).cloned()
});
if let Some(fp) = data {
let data = serde_json::to_string(&fp).unwrap_or_default();
Ok(data.to_string())
} else {
Ok("{}".to_string())
@@ -164,3 +166,4 @@ impl McpTool for GetEnvironmentDetailsHandler {
}
+30 -57
View File
@@ -368,60 +368,57 @@ impl McpTool for OmniSearchHandler {
}
}
});
for t in state.tasks.read() {
state.tasks.read_with(|all_tasks| {
for t in all_tasks {
if matches
.iter()
.any(|(id, typ, _, _, _)| id == &t.id && typ == "task")
{
tasks.push(t);
tasks.push(t.clone());
}
}
for s in state.snippets.read() {
});
state.snippets.read_with(|all_snippets| {
for s in all_snippets {
if matches
.iter()
.any(|(id, typ, _, _, _)| id == &s.name && typ == "snippet")
{
snippets.push(s);
snippets.push(s.clone());
}
}
for a in state.adrs.read() {
});
state.adrs.read_with(|all_adrs| {
for a in all_adrs {
if matches
.iter()
.any(|(id, typ, _, _, _)| id == &a.id && typ == "adr")
{
adrs.push(a);
adrs.push(a.clone());
}
}
});
let q = req.query.to_lowercase();
let tech_debts: Vec<_> = state
.tech_debts
.read()
.into_iter()
.filter(|d| {
let tech_debts = state.tech_debts.read_with(|debts| {
debts.iter().filter(|d| {
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
&& (contains_ignore_ascii_case(&d.description, &q)
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
})
.collect();
let memos: Vec<_> = state
.handoff_memos
.read()
.into_iter()
.filter(|m| {
}).cloned().collect::<Vec<_>>()
});
let memos = state.handoff_memos.read_with(|memos| {
memos.iter().filter(|m| {
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
&& contains_ignore_ascii_case(&m.content, &q)
})
.collect();
let error_fixes: Vec<_> = state
.error_fixes
.read()
.into_iter()
.filter(|f| {
}).cloned().collect::<Vec<_>>()
});
let error_fixes = state.error_fixes.read_with(|fixes| {
fixes.iter().filter(|f| {
contains_ignore_ascii_case(&f.signature, &q)
|| contains_ignore_ascii_case(&f.solution, &q)
})
.collect();
}).cloned().collect::<Vec<_>>()
});
let report = serde_json::json!({
"knowledge_graph": kg.entities,
@@ -453,36 +450,11 @@ impl McpTool for GetProjectHealthHandler {
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
let active_tasks = state
.tasks
.read()
.into_iter()
.filter(|t| t.status != "done")
.count();
let unresolved_debt = state
.tech_debts
.read()
.into_iter()
.filter(|d| d.namespace == req.namespace && !d.is_resolved)
.count();
let unread_memos = state
.handoff_memos
.read()
.into_iter()
.filter(|m| m.namespace == req.namespace)
.count();
let active_milestones = state
.milestones
.read()
.into_iter()
.filter(|m| m.namespace == req.namespace && m.status != "done")
.count();
let remaining_checklists = state
.pr_checklists
.read()
.into_iter()
.filter(|c| c.namespace == req.namespace)
.count();
let active_tasks = state.tasks.read_with(|tasks| tasks.iter().filter(|t| t.status != "done").count());
let unresolved_debt = state.tech_debts.read_with(|debts| debts.iter().filter(|d| d.namespace == req.namespace && !d.is_resolved).count());
let unread_memos = state.handoff_memos.read_with(|memos| memos.iter().filter(|m| m.namespace == req.namespace).count());
let active_milestones = state.milestones.read_with(|milestones| milestones.iter().filter(|m| m.namespace == req.namespace && m.status != "done").count());
let remaining_checklists = state.pr_checklists.read_with(|checklists| checklists.iter().filter(|c| c.namespace == req.namespace).count());
let report = serde_json::json!({
"active_tasks": active_tasks,
@@ -498,3 +470,4 @@ impl McpTool for GetProjectHealthHandler {
use crate::handlers_v2::utils::*;
+3 -18
View File
@@ -254,24 +254,9 @@ impl McpTool for GenerateStandupReportHandler {
.unwrap_or_default()
.as_secs()
.saturating_sub(req.hours_lookback * 3600);
let tasks = state
.tasks
.read()
.into_iter()
.filter(|t| t.updated_at >= cutoff)
.collect::<Vec<_>>();
let changes = state
.ledger
.read()
.into_iter()
.filter(|c| c.timestamp >= cutoff)
.collect::<Vec<_>>();
let summaries = state
.session_summaries
.read()
.into_iter()
.filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff)
.collect::<Vec<_>>();
let tasks = state.tasks.read_with(|items| items.iter().filter(|t| t.updated_at >= cutoff).cloned().collect::<Vec<_>>());
let changes = state.ledger.read_with(|items| items.iter().filter(|c| c.timestamp >= cutoff).cloned().collect::<Vec<_>>());
let summaries = state.session_summaries.read_with(|items| items.iter().filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff).cloned().collect::<Vec<_>>());
let report = serde_json::json!({ "tasks_updated": tasks, "code_changes": changes, "session_summaries": summaries });
Ok(report.to_string())
}
+6 -9
View File
@@ -147,17 +147,14 @@ impl McpTool for SearchSnippetsHandler {
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
let req: SearchSnippetsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
let query = req.query.to_lowercase();
let snippets = state.snippets.read();
let mut results = Vec::new();
for s in snippets {
if contains_ignore_ascii_case(&s.name, &query)
let data = state.snippets.read_with(|snippets| {
let results: Vec<_> = snippets.iter().filter(|s| {
contains_ignore_ascii_case(&s.name, &query)
|| contains_ignore_ascii_case(&s.description, &query)
|| contains_ignore_ascii_case(&s.language, &query)
{
results.push(s);
}
}
let data = serde_json::to_string(&results).unwrap_or_default();
}).cloned().collect();
serde_json::to_string(&results).unwrap_or_default()
});
Ok(data.to_string())
}
}
+18 -21
View File
@@ -355,28 +355,25 @@ async fn run_server(state: Arc<MemoryState>) -> Result<(), Box<dyn std::error::E
get({
let state_clone = app_state.handler.state.clone();
move || async move {
let (entities, relations) = {
let graph = state_clone.get_full_graph();
(graph.entities.len(), graph.relations.len())
};
let tasks = state_clone.tasks.read().len();
let snippets = state_clone.snippets.read().len();
let tech_debts = state_clone.tech_debts.read().len();
let adrs = state_clone.adrs.read().len();
let (entities, relations) = state_clone.read_graph(|g| (g.entities.len(), g.relations.len()));
let tasks = state_clone.tasks.read_with(|items| items.len());
let snippets = state_clone.snippets.read_with(|items| items.len());
let tech_debts = state_clone.tech_debts.read_with(|items| items.len());
let adrs = state_clone.adrs.read_with(|items| items.len());
let ledger = state_clone.ledger.read().len();
let sticky = state_clone.sticky.read().len();
let error_fixes = state_clone.error_fixes.read().len();
let pinned_files = state_clone.pinned_files.read().len();
let session_summaries = state_clone.session_summaries.read().len();
let handoff_memos = state_clone.handoff_memos.read().len();
let env_fingerprints = state_clone.env_fingerprints.read().len();
let env_requirements = state_clone.env_requirements.read().len();
let milestones = state_clone.milestones.read().len();
let environments = state_clone.environments.read().len();
let pr_checklists = state_clone.pr_checklists.read().len();
let gates = state_clone.gates.read().len();
let context_workspaces = state_clone.context_workspaces.read().len();
let ledger = state_clone.ledger.read_with(|items| items.len());
let sticky = state_clone.sticky.read_with(|items| items.len());
let error_fixes = state_clone.error_fixes.read_with(|items| items.len());
let pinned_files = state_clone.pinned_files.read_with(|items| items.len());
let session_summaries = state_clone.session_summaries.read_with(|items| items.len());
let handoff_memos = state_clone.handoff_memos.read_with(|items| items.len());
let env_fingerprints = state_clone.env_fingerprints.read_with(|items| items.len());
let env_requirements = state_clone.env_requirements.read_with(|items| items.len());
let milestones = state_clone.milestones.read_with(|items| items.len());
let environments = state_clone.environments.read_with(|items| items.len());
let pr_checklists = state_clone.pr_checklists.read_with(|items| items.len());
let gates = state_clone.gates.read_with(|items| items.len());
let context_workspaces = state_clone.context_workspaces.read_with(|items| items.len());
axum::Json(serde_json::json!({
"entities": entities,