From 53cec04646576d3a55d431b6d6820455a26ffd69 Mon Sep 17 00:00:00 2001 From: andrewgu-oai Date: Thu, 20 Aug 2026 21:44:00 +0000 Subject: [PATCH] Optimize case-insensitive thread history matching (#39802) ## What changed Map lowercase match offsets back to the original thread text with monotonic span cursors. This avoids rescanning all character spans for every occurrence while preserving the original byte ranges returned for matches. GitOrigin-RevId: 363fba5d56813c3aeb2a7ede1d7275147a9ef51a --- .../src/local/thread_history/search.rs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/codex-rs/thread-store/src/local/thread_history/search.rs b/codex-rs/thread-store/src/local/thread_history/search.rs index 59c49e4820..28e0b55a31 100644 --- a/codex-rs/thread-store/src/local/thread_history/search.rs +++ b/codex-rs/thread-store/src/local/thread_history/search.rs @@ -414,21 +414,22 @@ impl LiteralMatcher { lowercase_start = lowercase_end; } + // Use two-pointer method to find matches in linear time. + let mut start_span = 0; + let mut end_span = 0; lowercase_text .match_indices(self.lowercase_needle.as_str()) .take(limit) .filter_map(|(start, matched)| { let end = start.saturating_add(matched.len()); - let original_start = spans - .iter() - .find(|(lowercase, _)| lowercase.contains(&start))? - .1 - .start; - let original_end = spans - .iter() - .find(|(lowercase, _)| lowercase.contains(&end.saturating_sub(1)))? - .1 - .end; + while spans.get(start_span)?.0.end <= start { + start_span += 1; + } + while spans.get(end_span)?.0.end <= end.saturating_sub(1) { + end_span += 1; + } + let original_start = spans.get(start_span)?.1.start; + let original_end = spans.get(end_span)?.1.end; Some(original_start..original_end) }) .collect()