Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Feb 4, 2026

⚡️ This pull request contains optimizations for PR #1377

If you approve this dependent PR, these changes will be merged into the original PR branch js-trace.

This PR will be automatically closed if the original PR is merged.


📄 18% (0.18x) speedup for JavaScriptTracer._get_function_alias in codeflash/languages/javascript/tracer.py

⏱️ Runtime : 294 microseconds 250 microseconds (best of 250 runs)

📝 Explanation and details

The optimization achieves a 17% runtime improvement by eliminating redundant regex compilation overhead.

Key Changes:

  • Moved the regex pattern compilation (r"[^a-zA-Z0-9]") from inside _get_function_alias to a module-level constant _NON_ALNUM_RE
  • Changed from re.sub(r"[^a-zA-Z0-9]", "_", module_path) to _NON_ALNUM_RE.sub("_", module_path)

Why This Is Faster:
In the original code, re.sub() compiles the regex pattern on every function call. Python's re.sub() internally compiles the pattern, checks a cache, and performs the substitution. Even with caching, this lookup and compilation check adds overhead.

By pre-compiling the pattern once at module load time, we eliminate this repeated compilation overhead. The line profiler data confirms this - the regex substitution line dropped from 9.45ms (82.3% of time) to 4.03ms (66.7% of time), cutting the bottleneck in half.

Performance Characteristics:
The annotated tests show consistent improvements across all scenarios:

  • Simple paths: 35-50% faster on individual calls (2-4μs range)
  • Complex paths with many special characters: 30-40% faster (still significant)
  • Very long inputs: Smaller but measurable gains (7-19% on 100+ directory levels, 1.4% on extreme 500-directory paths)

The optimization is most effective for typical usage patterns with moderate path complexity, where the regex compilation overhead is a significant fraction of total execution time. For extremely long inputs where string manipulation dominates, the relative benefit decreases but remains positive.

Impact on Workloads:
Since _get_function_alias is called 3,341 times in the profiling run and is used to generate function aliases for JavaScript imports/tracing, this optimization provides compounding benefits in real-world scenarios where many functions are being traced or instrumented. The cumulative time savings scale linearly with call frequency.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 47 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
from pathlib import Path

# imports
import pytest
from codeflash.languages.javascript.tracer import JavaScriptTracer

class TestGetFunctionAliasBasic:
    """Basic test cases for _get_function_alias function."""

    def test_simple_module_and_function_no_class(self):
        """Test basic case with simple module path and function name, no class."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/utils.js", "processData"); result = codeflash_output # 4.15μs -> 2.96μs (39.9% faster)

    def test_simple_module_and_function_with_class(self):
        """Test basic case with simple module path, function name, and class name."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/utils.js", "processData", "Helper"); result = codeflash_output # 3.77μs -> 2.79μs (34.8% faster)

    def test_module_with_slashes(self):
        """Test module path containing directory separators."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/components/Button.js", "render"); result = codeflash_output # 3.86μs -> 2.88μs (34.2% faster)

    def test_module_with_slashes_and_class(self):
        """Test module path with slashes combined with class name."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/components/Button.js", "render", "ButtonComponent"); result = codeflash_output # 3.79μs -> 2.79μs (36.0% faster)

    def test_function_with_camel_case(self):
        """Test function name in camelCase format."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "calculateTotalPrice"); result = codeflash_output # 3.24μs -> 2.31μs (39.8% faster)

    def test_function_with_snake_case_converted(self):
        """Test function name with underscores (already valid)."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "calculate_total"); result = codeflash_output # 3.33μs -> 2.27μs (46.3% faster)

    def test_class_with_camel_case(self):
        """Test class name in PascalCase format."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "init", "MyClass"); result = codeflash_output # 3.37μs -> 2.29μs (46.7% faster)

    def test_module_path_with_hyphens(self):
        """Test module path containing hyphens (should be converted to underscores)."""
        codeflash_output = JavaScriptTracer._get_function_alias("my-module/utils.js", "process"); result = codeflash_output # 3.82μs -> 2.73μs (40.1% faster)

    def test_module_path_with_dots(self):
        """Test module path containing dots (should be converted to underscores)."""
        codeflash_output = JavaScriptTracer._get_function_alias("src.utils.js", "run"); result = codeflash_output # 3.59μs -> 2.50μs (43.8% faster)

    def test_module_path_with_special_characters(self):
        """Test module path with various special characters."""
        codeflash_output = JavaScriptTracer._get_function_alias("src@/utils!.js", "test"); result = codeflash_output # 3.77μs -> 2.79μs (34.8% faster)

    def test_empty_function_name(self):
        """Test with empty function name."""
        codeflash_output = JavaScriptTracer._get_function_alias("module.js", ""); result = codeflash_output # 3.31μs -> 2.19μs (51.3% faster)

    def test_empty_class_name(self):
        """Test with empty class name (should still work)."""
        codeflash_output = JavaScriptTracer._get_function_alias("module.js", "func", ""); result = codeflash_output # 3.44μs -> 2.42μs (41.7% faster)

    def test_module_path_only_special_chars(self):
        """Test module path containing only special characters."""
        codeflash_output = JavaScriptTracer._get_function_alias("@#$%^&*", "func"); result = codeflash_output # 3.95μs -> 2.90μs (36.3% faster)

class TestGetFunctionAliasEdgeCases:
    """Edge case test cases for _get_function_alias function."""

    def test_module_path_with_leading_special_chars(self):
        """Test module path with special characters at the beginning."""
        codeflash_output = JavaScriptTracer._get_function_alias("@@@src/utils.js", "test"); result = codeflash_output # 4.09μs -> 3.01μs (36.0% faster)

    def test_module_path_with_trailing_special_chars(self):
        """Test module path with special characters at the end."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/utils.js@@@", "test"); result = codeflash_output # 3.95μs -> 2.93μs (34.9% faster)

    def test_module_path_with_consecutive_special_chars(self):
        """Test module path with consecutive special characters."""
        codeflash_output = JavaScriptTracer._get_function_alias("src///utils.js", "test"); result = codeflash_output # 3.67μs -> 2.73μs (34.6% faster)

    def test_function_name_with_numbers(self):
        """Test function name containing numbers."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "process123Data"); result = codeflash_output # 3.31μs -> 2.25μs (47.3% faster)

    def test_module_path_with_numbers(self):
        """Test module path containing numbers."""
        codeflash_output = JavaScriptTracer._get_function_alias("src2/utils3.js", "test"); result = codeflash_output # 3.55μs -> 2.44μs (45.1% faster)

    def test_very_long_module_path(self):
        """Test with very long module path."""
        long_path = "a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/module.js"
        codeflash_output = JavaScriptTracer._get_function_alias(long_path, "func"); result = codeflash_output # 6.08μs -> 5.10μs (19.3% faster)

    def test_very_long_function_name(self):
        """Test with very long function name."""
        long_func = "a" * 500
        codeflash_output = JavaScriptTracer._get_function_alias("module.js", long_func); result = codeflash_output # 3.52μs -> 2.38μs (48.1% faster)

    def test_module_with_windows_path_separators(self):
        """Test module path with backslash separators (Windows-style)."""
        codeflash_output = JavaScriptTracer._get_function_alias("src\\utils.js", "test"); result = codeflash_output # 3.57μs -> 2.60μs (37.5% faster)

    def test_unicode_in_function_name(self):
        """Test function name with unicode characters."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "process\u00e9Data"); result = codeflash_output # 3.34μs -> 2.27μs (46.7% faster)

    def test_only_spaces_as_module(self):
        """Test with spaces in module path."""
        codeflash_output = JavaScriptTracer._get_function_alias("src utils.js", "func"); result = codeflash_output # 3.51μs -> 2.50μs (40.6% faster)

    def test_class_name_none_explicit(self):
        """Test with explicit None as class_name parameter."""
        codeflash_output = JavaScriptTracer._get_function_alias("module.js", "func", None); result = codeflash_output # 3.21μs -> 2.17μs (47.4% faster)

    def test_all_special_chars_in_all_parts(self):
        """Test with special characters in module, function, and class names."""
        codeflash_output = JavaScriptTracer._get_function_alias("@module!", "func@#$", "Class$%"); result = codeflash_output # 3.62μs -> 2.46μs (46.7% faster)

    def test_module_path_with_multiple_dots(self):
        """Test module path with multiple consecutive dots."""
        codeflash_output = JavaScriptTracer._get_function_alias("src...utils.js", "test"); result = codeflash_output # 3.87μs -> 2.81μs (37.9% faster)

    def test_module_path_starting_with_dot(self):
        """Test module path starting with dot (relative import)."""
        codeflash_output = JavaScriptTracer._get_function_alias("./src/utils.js", "test"); result = codeflash_output # 3.80μs -> 2.75μs (37.8% faster)

    def test_module_path_with_double_slash(self):
        """Test module path with double slashes."""
        codeflash_output = JavaScriptTracer._get_function_alias("src//utils.js", "test"); result = codeflash_output # 3.76μs -> 2.67μs (41.0% faster)

    def test_class_name_with_spaces(self):
        """Test class name containing spaces."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "func", "My Class"); result = codeflash_output # 3.27μs -> 2.39μs (36.4% faster)

    def test_function_name_with_hyphens(self):
        """Test function name with hyphens (uncommon but possible)."""
        codeflash_output = JavaScriptTracer._get_function_alias("utils.js", "process-data"); result = codeflash_output # 3.27μs -> 2.27μs (43.6% faster)

    def test_mixed_separators_in_path(self):
        """Test path with mixed forward and backward slashes."""
        codeflash_output = JavaScriptTracer._get_function_alias("src/sub\\utils.js", "test"); result = codeflash_output # 3.75μs -> 2.69μs (39.0% faster)

class TestGetFunctionAliasLargeScale:
    """Large scale test cases for _get_function_alias function."""

    def test_many_directory_levels(self):
        """Test with deeply nested directory structure."""
        # Create a path with 100 directory levels
        long_path = "/".join([f"dir{i}" for i in range(100)]) + "/module.js"
        codeflash_output = JavaScriptTracer._get_function_alias(long_path, "func"); result = codeflash_output # 16.5μs -> 15.3μs (7.46% faster)

    def test_many_special_character_replacements(self):
        """Test with path containing many special characters requiring replacement."""
        # Create a path with many special characters
        special_path = "s@r#c$%/u&t*i(l)s-.-j.s"
        codeflash_output = JavaScriptTracer._get_function_alias(special_path, "process"); result = codeflash_output # 4.85μs -> 3.70μs (31.2% faster)

    def test_repeated_function_calls_consistency(self):
        """Test that repeated calls with same parameters return identical results."""
        module = "src/components/Button.js"
        func = "handleClick"
        cls = "ButtonComponent"
        
        results = [JavaScriptTracer._get_function_alias(module, func, cls) for _ in range(1000)]

    def test_varied_inputs_consistency(self):
        """Test consistency with varied inputs across many iterations."""
        test_cases = [
            ("module1.js", "func1", None),
            ("path/to/module2.js", "func2", "Class1"),
            ("a@b#c$.js", "test_func", "TestClass"),
            ("src///utils.js", "process", "Helper"),
        ]
        
        # Run each test case 250 times
        for module, func, cls in test_cases:
            results = [JavaScriptTracer._get_function_alias(module, func, cls) for _ in range(250)]

    def test_multiple_class_names_same_module_function(self):
        """Test that different class names produce different results for same module/function."""
        module = "utils.js"
        func = "process"
        class_names = [f"Class{i}" for i in range(100)]
        
        results = [JavaScriptTracer._get_function_alias(module, func, cls) for cls in class_names]
        # Each should contain the class name
        for i, result in enumerate(results):
            pass

    def test_multiple_functions_same_module_class(self):
        """Test that different function names produce different results for same module/class."""
        module = "utils.js"
        cls = "Helper"
        functions = [f"func{i}" for i in range(100)]
        
        results = [JavaScriptTracer._get_function_alias(module, func, cls) for func in functions]
        # Each should contain the function name
        for i, result in enumerate(results):
            pass

    def test_multiple_modules_same_function_class(self):
        """Test that different module paths produce different results for same function/class."""
        func = "process"
        cls = "Helper"
        modules = [f"src/mod{i}/utils.js" for i in range(100)]
        
        results = [JavaScriptTracer._get_function_alias(module, func, cls) for module in modules]

    def test_performance_with_long_inputs(self):
        """Test performance characteristics with very long input strings."""
        import time

        # Create a very long module path (but within reasonable limits)
        long_module = "/".join([f"directory_{i}" for i in range(500)]) + "/module.js"
        long_func = "a" * 1000
        long_class = "B" * 1000
        
        # Time the execution
        start = time.time()
        codeflash_output = JavaScriptTracer._get_function_alias(long_module, long_func, long_class); result = codeflash_output # 127μs -> 125μs (1.39% faster)
        elapsed = time.time() - start

    def test_no_output_size_explosion(self):
        """Test that output doesn't grow unexpectedly with input size."""
        module = "a" * 500 + "/module.js"
        func = "b" * 500
        cls = "C" * 500
        
        codeflash_output = JavaScriptTracer._get_function_alias(module, func, cls); result = codeflash_output # 6.86μs -> 5.74μs (19.5% faster)
        
        # Result length should be roughly proportional to input
        # (not quadratic or exponential)
        total_input_len = len(module) + len(func) + len(cls)

    def test_batch_processing_different_inputs(self):
        """Test processing a batch of different inputs."""
        test_data = [
            ("path1/utils.js", "func1", "Class1"),
            ("path2/utils.js", "func2", "Class2"),
            ("path3/utils.js", "func3", "Class3"),
            ("path4/utils.js", "func4", "Class4"),
            ("path5/utils.js", "func5", "Class5"),
        ] * 200  # 1000 total cases
        
        results = [JavaScriptTracer._get_function_alias(m, f, c) for m, f, c in test_data]
        # Results should correspond to their inputs
        for i in range(0, 1000, 5):
            idx = i % 5
            expected_class = f"Class{idx + 1}"
            expected_func = f"func{idx + 1}"

class TestGetFunctionAliasSpecialCharacterHandling:
    """Test cases specifically for special character handling."""

    def test_common_special_characters(self):
        """Test handling of common special characters."""
        special_chars = "!@#$%^&*()"
        codeflash_output = JavaScriptTracer._get_function_alias(special_chars + "module.js", "func"); result = codeflash_output # 4.64μs -> 3.58μs (29.7% faster)

    def test_alphanumeric_preservation(self):
        """Test that alphanumeric characters are preserved."""
        module = "Src123Module.js"
        func = "processData456"
        cls = "MyClass789"
        codeflash_output = JavaScriptTracer._get_function_alias(module, func, cls); result = codeflash_output # 3.55μs -> 2.44μs (45.1% faster)

    def test_underscore_preservation(self):
        """Test that underscores in input are preserved."""
        module = "src_utils_module.js"
        func = "process_data"
        cls = "My_Class"
        codeflash_output = JavaScriptTracer._get_function_alias(module, func, cls); result = codeflash_output # 3.76μs -> 2.67μs (40.4% faster)

    def test_multiple_consecutive_underscores(self):
        """Test handling of multiple consecutive underscores."""
        codeflash_output = JavaScriptTracer._get_function_alias("src___utils.js", "func"); result = codeflash_output # 3.77μs -> 2.73μs (38.2% faster)

    def test_strip_leading_underscores(self):
        """Test that leading underscores are stripped from module alias."""
        codeflash_output = JavaScriptTracer._get_function_alias("___module.js", "func"); result = codeflash_output # 3.81μs -> 2.69μs (41.3% faster)

    def test_strip_trailing_underscores(self):
        """Test that trailing underscores are stripped from module alias."""
        codeflash_output = JavaScriptTracer._get_function_alias("module___.js", "func"); result = codeflash_output # 3.71μs -> 2.60μs (42.3% faster)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-pr1377-2026-02-04T10.33.39 and push.

Codeflash Static Badge

KRRT7 and others added 2 commits February 4, 2026 05:19
Add comprehensive test coverage for JavaScript tracing:
- Unit tests for trace parsing (function_calls and legacy schemas)
- Unit tests for replay test generation (Jest and Vitest)
- E2E test for full tracing pipeline with npm dependencies
- Framework detection tests (Jest, Vitest, package.json)
The optimization achieves a **17% runtime improvement** by eliminating redundant regex compilation overhead. 

**Key Changes:**
- Moved the regex pattern compilation (`r"[^a-zA-Z0-9]"`) from inside `_get_function_alias` to a module-level constant `_NON_ALNUM_RE`
- Changed from `re.sub(r"[^a-zA-Z0-9]", "_", module_path)` to `_NON_ALNUM_RE.sub("_", module_path)`

**Why This Is Faster:**
In the original code, `re.sub()` compiles the regex pattern on every function call. Python's `re.sub()` internally compiles the pattern, checks a cache, and performs the substitution. Even with caching, this lookup and compilation check adds overhead.

By pre-compiling the pattern once at module load time, we eliminate this repeated compilation overhead. The line profiler data confirms this - the regex substitution line dropped from **9.45ms (82.3% of time)** to **4.03ms (66.7% of time)**, cutting the bottleneck in half.

**Performance Characteristics:**
The annotated tests show consistent improvements across all scenarios:
- **Simple paths**: 35-50% faster on individual calls (2-4μs range)
- **Complex paths with many special characters**: 30-40% faster (still significant)
- **Very long inputs**: Smaller but measurable gains (7-19% on 100+ directory levels, 1.4% on extreme 500-directory paths)

The optimization is most effective for typical usage patterns with moderate path complexity, where the regex compilation overhead is a significant fraction of total execution time. For extremely long inputs where string manipulation dominates, the relative benefit decreases but remains positive.

**Impact on Workloads:**
Since `_get_function_alias` is called 3,341 times in the profiling run and is used to generate function aliases for JavaScript imports/tracing, this optimization provides compounding benefits in real-world scenarios where many functions are being traced or instrumented. The cumulative time savings scale linearly with call frequency.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant