From a339bfaa7c1b13e4efd912ce2f625b8be2d494ad Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:08:51 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Optimize=20InteractiveT?= =?UTF-8?q?ranscript=20filter=20performance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 +++ .../web/src/components/InteractiveTranscript.tsx | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 603b207d0..ca1af7062 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -14,3 +14,6 @@ ## 2026-07-28 - Memoize text processing in React **Learning:** Performing expensive string manipulations like splitting long texts (`transcript.split('\n')`) or generating dynamic Regex expressions inside a component body causes significant CPU overhead on every re-render (like keystroke updates in a search box). **Action:** Extract pure transformation logic on static/infrequent data into `useMemo` hooks (e.g., memoizing the paragraph split on `transcript` and precomputing search `RegExp` based on `searchQuery`). +## 2026-07-23 - Optimize string operations in React filtering loops +**Learning:** Found an inefficiency in `InteractiveTranscript.tsx` where `.toLowerCase()` on the search query was evaluated *inside* a `.filter()` loop, repeating a constant operation O(N) times. Additionally, the expensive text matching was evaluated even if the speaker filter failed. +**Action:** When filtering large arrays in React `useMemo` hooks, always hoist constant operations (like query lowercasing) outside the loop and use short-circuit evaluation (`if (!matchesPreviousCondition) return false;`) to skip expensive string methods. Also remember to add safety checks like `val ? val.toLowerCase() : ''` to avoid crashes. diff --git a/apps/web/src/components/InteractiveTranscript.tsx b/apps/web/src/components/InteractiveTranscript.tsx index 21f79d91b..6f3e03fcc 100644 --- a/apps/web/src/components/InteractiveTranscript.tsx +++ b/apps/web/src/components/InteractiveTranscript.tsx @@ -166,12 +166,22 @@ export default function InteractiveTranscript({ ); const filteredSegments = useMemo(() => { + // Optimization: Pre-compute the lowercase search query outside the loop + // to prevent recalculating it for every segment. Also short-circuit the + // expensive string matching if the speaker filter already fails. + const lowerQuery = searchQuery ? searchQuery.toLowerCase() : ''; + return segments.filter((seg) => { const matchesSpeaker = !filterSpeaker || seg.speaker === filterSpeaker; + + // Short-circuit: if speaker doesn't match, we can skip the text search + if (!matchesSpeaker) return false; + const matchesSearch = - !searchQuery || - seg.text.toLowerCase().includes(searchQuery.toLowerCase()); - return matchesSpeaker && matchesSearch; + !lowerQuery || + (seg.text ? seg.text.toLowerCase().includes(lowerQuery) : false); + + return matchesSearch; }); }, [segments, filterSpeaker, searchQuery]); From 0ae83a5166d83f04e33f0870caea2841ecd88d6e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 18:14:24 +0000 Subject: [PATCH 2/2] chore: acknowledge governance halt