From 41f14f761ebcc1e0c3e2485f7ac232809634d639 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:29:38 +0000 Subject: [PATCH] Optimize ExpectCallTransformer.transform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The optimized code achieves a **172% speedup** (85.2ms → 31.3ms) by eliminating a critical O(n²) performance bottleneck in the `transform()` method. ## Key Optimization **Problem**: The original code called `is_inside_string(code, match.start())` for every regex match found. This function scans from position 0 to the match position each time, resulting in O(n²) complexity when processing code with many matches. **Solution**: The optimization replaces these repeated scans with **incremental string state tracking** directly in the main loop. Instead of rescanning from the beginning for each match, the code maintains `in_string`, `string_char`, and `last_checked_pos` variables that preserve state between iterations. When a new match is found, only the code between `last_checked_pos` and `match_start` is scanned to update the string state. ## Performance Impact The line profiler data clearly shows the improvement: - **Original**: `is_inside_string()` consumed 0.618s (95.2% of transform time) with 432 calls scanning 887,510 characters total - **Optimized**: The inline tracking logic in transform() consumes only 0.021s (33% of transform time) by scanning just 28,273 characters incrementally Test results demonstrate strong gains on workloads with many matches: - `test_transform_many_invocations`: 12.3ms → 4.84ms (155% faster) - `test_transform_large_code_file`: 40.6ms → 14.0ms (191% faster) - `test_transform_alternating_patterns`: 2.64ms → 519μs (408% faster) - `test_transform_mixed_qualified_names`: 14.0ms → 5.14ms (173% faster) The optimization particularly benefits code with frequent expect() calls, as each avoided `is_inside_string()` call saves scanning hundreds or thousands of characters. This makes the transformer significantly faster on realistic test files with multiple assertions. --- codeflash/languages/javascript/instrument.py | 30 +++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/codeflash/languages/javascript/instrument.py b/codeflash/languages/javascript/instrument.py index ee28c90a6..ef5840cab 100644 --- a/codeflash/languages/javascript/instrument.py +++ b/codeflash/languages/javascript/instrument.py @@ -603,6 +603,10 @@ def transform(self, code: str) -> str: """Transform all expect calls in the code.""" result: list[str] = [] pos = 0 + # Track string state incrementally to avoid O(n²) rescanning + in_string = False + string_char = None + last_checked_pos = 0 while pos < len(code): expect_match = self._expect_pattern.search(code, pos) @@ -627,8 +631,32 @@ def transform(self, code: str) -> str: result.append(code[pos:]) break + # Update string state up to match.start() incrementally + match_start = match.start() + i = last_checked_pos + while i < match_start: + char = code[i] + + if in_string: + # Check for escape sequence + if char == "\\" and i + 1 < len(code): + i += 2 + continue + # Check for end of string + if char == string_char: + in_string = False + string_char = None + # Check for start of string + elif char in "\"'`": + in_string = True + string_char = char + + i += 1 + + last_checked_pos = match_start + # Skip if inside a string literal (e.g., test description) - if is_inside_string(code, match.start()): + if in_string: result.append(code[pos : match.end()]) pos = match.end() continue