From b80e80cea5280beb187ec9cfa303d643459407d8 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 4 Jul 2026 21:23:45 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20search=20filter?= =?UTF-8?q?=20by=20avoiding=20array=20allocations=20and=20flatMap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 +++ frontend/src/App.tsx | 28 ++++++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index b45f9caa..1b660bda 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -60,3 +60,6 @@ Optimized metric route processing to O(N) by creating a mapping of routes direct ## 2026-06-25 - Avoid Map allocations in frontend ERD loops and mutate asyncpg records in-place **Learning:** The frontend `snapshotToGraph` iterates over thousands of columns to generate the graph, so repeated lookups and redundant collection assignments increase GC pressure. Backend snapshot column dictionaries are freshly instantiated for the payload, so `add_column_examples` can safely fill missing fields in place. **Action:** Reuse existing collections while aggregating relational data, create `Map`/`Set` entries only on first use, and check for missing example fields before calling expensive inference helpers. +## 2026-06-25 - Avoid array allocation and .flatMap() in frontend string searches +**Learning:** Using `.flatMap(...)` to collect fields across objects and then `.join(" ")` on them creates excessive array memory allocations, drastically degrading React rendering performance when iterating over many nodes during user typing or node rendering updates. +**Action:** Always short-circuit using explicit `for` loops and test properties sequentially, using `continue` or `break` upon finding a match rather than allocating and joining strings in hot loops. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e99700c5..06cb6dd8 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -182,19 +182,23 @@ export default function App() { if (!normalizedNodeSearch) return new Set(); const matches = new Set(); for (const node of nodes) { - const haystack = [ - node.data.title, - node.data.comment ?? "", - ...node.data.columns.flatMap((column) => [ - column.column_name, - column.data_type, - column.column_comment ?? "", - ]), - ] - .join(" ") - .toLocaleLowerCase(); - if (haystack.includes(normalizedNodeSearch)) { + if (node.data.title.toLocaleLowerCase().includes(normalizedNodeSearch)) { matches.add(node.id); + continue; + } + if (node.data.comment?.toLocaleLowerCase().includes(normalizedNodeSearch)) { + matches.add(node.id); + continue; + } + for (const column of node.data.columns) { + if ( + column.column_name.toLocaleLowerCase().includes(normalizedNodeSearch) || + column.data_type.toLocaleLowerCase().includes(normalizedNodeSearch) || + column.column_comment?.toLocaleLowerCase().includes(normalizedNodeSearch) + ) { + matches.add(node.id); + break; + } } } return matches;