Skip to content

⚡️ Speed up function get_optimized_code_for_module by 14% in PR #1717 (prepare-java-support-2)#1722

Closed
codeflash-ai[bot] wants to merge 423 commits intoprepare-java-support-2from
codeflash/optimize-pr1717-2026-03-02T18.58.47
Closed

⚡️ Speed up function get_optimized_code_for_module by 14% in PR #1717 (prepare-java-support-2)#1722
codeflash-ai[bot] wants to merge 423 commits intoprepare-java-support-2from
codeflash/optimize-pr1717-2026-03-02T18.58.47

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Mar 2, 2026

⚡️ This pull request contains optimizations for PR #1717

If you approve this dependent PR, these changes will be merged into the original PR branch prepare-java-support-2.

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


📄 14% (0.14x) speedup for get_optimized_code_for_module in codeflash/languages/code_replacer.py

⏱️ Runtime : 44.5 milliseconds 39.1 milliseconds (best of 23 runs)

📝 Explanation and details

The optimization replaces an if "key" in dict check followed by a separate dict[key] access in file_to_path() with a single try/except on KeyError, halving the dictionary operations in the 99% cache-hit path (from ~47% + 38% profiler time to ~71% in one lookup). It also guards two expensive logger calls—one constructing a large f-string with the entire optimized_code object—behind isEnabledFor(DEBUG/WARNING) checks, preventing format-string evaluation when logging is disabled. Line profiler shows the warning path dropped from 65.6% to 74.8% of total time, but because it fires on only 18 of 3136 calls the overall function runtime improved 13%, dominated by the dictionary micro-optimization on the hot cache-hit loop.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 3037 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
from pathlib import \
    Path  # used to construct Path objects for the function input

# imports
import pytest  # used for our unit tests
from codeflash.languages.code_replacer import get_optimized_code_for_module
from codeflash.models.models import \
    CodeStringsMarkdown  # real model class used by the function

def test_exact_path_match_returns_code():
    # Create a real CodeStringsMarkdown instance (uses real Pydantic model constructor).
    optimized = CodeStringsMarkdown()  # no args uses defaults; safe to mutate its _cache PrivateAttr
    # Populate the internal cache directly so file_to_path() will return this mapping quickly.
    optimized._cache["file_to_path"] = {"src/module.py": 'print("hello from module")'}
    # Call the function with a Path that stringifies to the mapping key.
    codeflash_output = get_optimized_code_for_module(Path("src/module.py"), optimized); result = codeflash_output # 8.03μs -> 6.40μs (25.4% faster)

def test_none_key_fallback_used_when_only_none_present():
    # When the mapping contains exactly one key "None", the function should return its value
    optimized = CodeStringsMarkdown()
    # Simulate AI server behavior where file_path was None -> str(None) == "None".
    optimized._cache["file_to_path"] = {"None": "def generated():\n    return 42"}
    # Use any Path; since there is no exact match but only "None" entry, it should be used.
    codeflash_output = get_optimized_code_for_module(Path("some/expected/path.py"), optimized); result = codeflash_output # 13.0μs -> 6.94μs (87.6% faster)

def test_none_key_with_other_entries_returns_empty_string():
    # If "None" appears but there are other entries too, the fallback should NOT be used.
    optimized = CodeStringsMarkdown()
    optimized._cache["file_to_path"] = {"None": "x = 1", "other.py": "y = 2"}
    # No direct match for the requested path -> should return empty string (fallback not allowed).
    codeflash_output = get_optimized_code_for_module(Path("missing.py"), optimized); result = codeflash_output # 955μs -> 927μs (3.02% faster)

def test_empty_codes_results_in_empty_string_and_no_exception():
    # If there are no code strings at all, file_to_path() will build an empty mapping
    # and the function should return an empty string without raising.
    optimized = CodeStringsMarkdown()  # code_strings defaults to empty list
    # Ensure cache is empty so file_to_path() builds the mapping from code_strings.
    optimized._cache.clear()
    codeflash_output = get_optimized_code_for_module(Path("any/path.py"), optimized); result = codeflash_output # 863μs -> 890μs (3.02% slower)

def test_special_characters_in_path_are_handled_via_str_conversion():
    # Ensure that keys with special/unicode characters are matched using str(path).
    optimized = CodeStringsMarkdown()
    special_key = "weird/çhår$.py"
    optimized._cache["file_to_path"] = {special_key: "print('weird')"}
    # Construct a Path with the same characters; Path.__str__ will produce an identical string.
    codeflash_output = get_optimized_code_for_module(Path(special_key), optimized); result = codeflash_output # 8.28μs -> 6.61μs (25.2% faster)

def test_path_string_format_mismatch_returns_empty():
    # Demonstrate that non-normalized path representations must exactly match the stored string.
    optimized = CodeStringsMarkdown()
    # Store a normalized path string in the cache.
    optimized._cache["file_to_path"] = {"a/file.py": "content"}
    # Provide a Path that stringifies to a different representation (contains ..).
    # This should not match and should therefore return empty string.
    codeflash_output = get_optimized_code_for_module(Path("a/../a/file.py"), optimized); result = codeflash_output # 904μs -> 917μs (1.47% slower)

def test_large_mapping_lookup_correctness_and_stability():
    # Build a large mapping of 1000 entries to simulate realistic load.
    optimized = CodeStringsMarkdown()
    large_map = {f"file_{i}.py": f"code_{i}" for i in range(1000)}
    optimized._cache["file_to_path"] = large_map
    # Pick a mid-range file to look up.
    target = "file_500.py"
    # Call the function once and verify correctness.
    codeflash_output = get_optimized_code_for_module(Path(target), optimized); single_result = codeflash_output # 8.28μs -> 6.62μs (25.0% faster)
    # Call the function multiple times (1000 iterations) to ensure deterministic stability.
    for _ in range(1000):
        codeflash_output = get_optimized_code_for_module(Path(target), optimized); repeated = codeflash_output # 4.35ms -> 2.88ms (51.3% faster)

def test_large_scale_no_match_with_many_entries_returns_empty():
    # Ensure that even with many entries, missing keys result in empty string.
    optimized = CodeStringsMarkdown()
    # Create 1000 unrelated entries.
    optimized._cache["file_to_path"] = {f"other_{i}.py": f"v{i}" for i in range(1000)}
    # Request a path that is not present.
    codeflash_output = get_optimized_code_for_module(Path("nonexistent.py"), optimized); result = codeflash_output # 19.2ms -> 19.4ms (1.20% slower)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
from pathlib import Path

# imports
import pytest
from codeflash.languages.code_replacer import get_optimized_code_for_module
from codeflash.models.models import CodeString, CodeStringsMarkdown

def test_basic_exact_path_match():
    """Test that the function returns code when the file path matches exactly."""
    # Create a CodeString with a specific file path
    code_string = CodeString(file_path=Path("module.py"), code="print('hello')")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Call the function with the same path
    codeflash_output = get_optimized_code_for_module(Path("module.py"), optimized_code); result = codeflash_output # 15.0μs -> 15.8μs (5.20% slower)

def test_multiple_code_strings_returns_correct_one():
    """Test that the function returns the correct code when multiple code strings exist."""
    # Create multiple code strings for different modules
    code_string_1 = CodeString(file_path=Path("module_a.py"), code="code_a")
    code_string_2 = CodeString(file_path=Path("module_b.py"), code="code_b")
    code_string_3 = CodeString(file_path=Path("module_c.py"), code="code_c")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string_1, code_string_2, code_string_3])
    
    # Query for module_b
    codeflash_output = get_optimized_code_for_module(Path("module_b.py"), optimized_code); result = codeflash_output # 15.2μs -> 16.2μs (5.83% slower)

def test_nested_path_match():
    """Test that the function correctly handles nested file paths."""
    # Create a code string with a nested path
    code_string = CodeString(file_path=Path("src/utils/helper.py"), code="nested_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with the same nested path
    codeflash_output = get_optimized_code_for_module(Path("src/utils/helper.py"), optimized_code); result = codeflash_output # 12.8μs -> 14.2μs (9.54% slower)

def test_fallback_to_none_path_single_code_block():
    """Test fallback behavior when queried path doesn't match but only one code block with None path exists."""
    # Create a code string with None file_path
    code_string = CodeString(file_path=None, code="fallback_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with a path that doesn't match anything
    codeflash_output = get_optimized_code_for_module(Path("any_module.py"), optimized_code); result = codeflash_output # 17.1μs -> 13.2μs (29.4% faster)

def test_no_match_no_fallback_returns_empty_string():
    """Test that the function returns empty string when no match and no fallback is available."""
    # Create code strings that don't match the query path
    code_string_1 = CodeString(file_path=Path("module_a.py"), code="code_a")
    code_string_2 = CodeString(file_path=Path("module_b.py"), code="code_b")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string_1, code_string_2])
    
    # Query with a path that doesn't exist
    codeflash_output = get_optimized_code_for_module(Path("nonexistent.py"), optimized_code); result = codeflash_output # 1.28ms -> 1.29ms (1.15% slower)

def test_exact_match_preferred_over_fallback():
    """Test that exact path match is preferred over None path fallback."""
    # Create code strings with both exact match and None path
    code_string_exact = CodeString(file_path=Path("module.py"), code="exact_code")
    code_string_none = CodeString(file_path=None, code="fallback_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string_exact, code_string_none])
    
    # Query with the exact path
    codeflash_output = get_optimized_code_for_module(Path("module.py"), optimized_code); result = codeflash_output # 14.6μs -> 15.3μs (4.52% slower)

def test_multiline_code_string():
    """Test that multiline code strings are preserved correctly."""
    # Create a code string with multiple lines
    multiline_code = """def hello():
    print("world")
    return 42"""
    code_string = CodeString(file_path=Path("multi.py"), code=multiline_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("multi.py"), optimized_code); result = codeflash_output # 13.6μs -> 14.6μs (6.53% slower)

def test_special_characters_in_code():
    """Test that special characters in code are preserved."""
    # Create code with special characters
    special_code = "code = 'string with \"quotes\" and \\n newlines'; print(r'raw \\path')"
    code_string = CodeString(file_path=Path("special.py"), code=special_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("special.py"), optimized_code); result = codeflash_output # 13.0μs -> 14.0μs (7.01% slower)

def test_empty_code_strings_list():
    """Test behavior when code_strings list is empty."""
    # Create an empty CodeStringsMarkdown
    optimized_code = CodeStringsMarkdown(code_strings=[])
    
    # Query for any path
    codeflash_output = get_optimized_code_for_module(Path("any.py"), optimized_code); result = codeflash_output # 868μs -> 878μs (1.13% slower)

def test_empty_code_string_value():
    """Test that empty code string values are returned correctly."""
    # Create a code string with empty code
    code_string = CodeString(file_path=Path("empty.py"), code="")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("empty.py"), optimized_code); result = codeflash_output # 13.7μs -> 14.6μs (6.32% slower)

def test_path_with_dots():
    """Test that paths with dots (like ..) are handled correctly."""
    # Create a code string with a path containing dots
    code_string = CodeString(file_path=Path("../parent/module.py"), code="parent_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with the same path
    codeflash_output = get_optimized_code_for_module(Path("../parent/module.py"), optimized_code); result = codeflash_output # 13.4μs -> 14.4μs (6.98% slower)

def test_absolute_path_handling():
    """Test that absolute paths are handled by Path string conversion."""
    # Create a code string with absolute path
    code_string = CodeString(file_path=Path("/absolute/path/to/module.py"), code="absolute_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with the same absolute path
    codeflash_output = get_optimized_code_for_module(Path("/absolute/path/to/module.py"), optimized_code); result = codeflash_output # 14.2μs -> 15.0μs (5.16% slower)

def test_path_with_special_characters():
    """Test paths with special characters like hyphens and underscores."""
    # Create a code string with special characters in path
    code_string = CodeString(file_path=Path("my-module_v2.py"), code="special_path_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with the same path
    codeflash_output = get_optimized_code_for_module(Path("my-module_v2.py"), optimized_code); result = codeflash_output # 12.3μs -> 13.5μs (8.41% slower)

def test_only_none_path_in_multiple_code_strings_no_fallback():
    """Test that None path is NOT used as fallback when multiple code strings exist."""
    # Create multiple code strings where one has None path
    code_string_1 = CodeString(file_path=Path("module_a.py"), code="code_a")
    code_string_none = CodeString(file_path=None, code="none_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string_1, code_string_none])
    
    # Query with a path that doesn't match any existing path
    codeflash_output = get_optimized_code_for_module(Path("nonexistent.py"), optimized_code); result = codeflash_output # 1.25ms -> 1.26ms (1.13% slower)

def test_whitespace_only_code():
    """Test that code with only whitespace is handled correctly."""
    # Create a code string with only whitespace
    whitespace_code = "   \n  \t  \n  "
    code_string = CodeString(file_path=Path("whitespace.py"), code=whitespace_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("whitespace.py"), optimized_code); result = codeflash_output # 13.7μs -> 14.5μs (5.39% slower)

def test_very_long_code_string():
    """Test that very long code strings are handled correctly."""
    # Create a very long code string
    long_code = "x = 1\n" * 10000  # 10000 lines
    code_string = CodeString(file_path=Path("long.py"), code=long_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("long.py"), optimized_code); result = codeflash_output # 21.5μs -> 25.4μs (15.2% slower)

def test_unicode_in_code():
    """Test that unicode characters in code are preserved."""
    # Create code with unicode characters
    unicode_code = "message = '你好世界'; print('Привет мир'); emoji = '🚀'"
    code_string = CodeString(file_path=Path("unicode.py"), code=unicode_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("unicode.py"), optimized_code); result = codeflash_output # 13.9μs -> 15.2μs (8.43% slower)

def test_path_case_sensitivity():
    """Test that path matching is case-sensitive."""
    # Create code strings with different cases
    code_string_lower = CodeString(file_path=Path("module.py"), code="lowercase_code")
    code_string_upper = CodeString(file_path=Path("Module.py"), code="uppercase_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string_lower, code_string_upper])
    
    # Query with lowercase path
    codeflash_output = get_optimized_code_for_module(Path("module.py"), optimized_code); result_lower = codeflash_output # 14.3μs -> 15.3μs (6.99% slower)
    # Query with uppercase path
    codeflash_output = get_optimized_code_for_module(Path("Module.py"), optimized_code); result_upper = codeflash_output # 5.72μs -> 4.36μs (31.3% faster)
    # Query with different case
    codeflash_output = get_optimized_code_for_module(Path("MODULE.py"), optimized_code); result_different = codeflash_output # 1.43ms -> 1.43ms (0.298% faster)

def test_single_character_code():
    """Test that single character code strings work correctly."""
    # Create code with single character
    code_string = CodeString(file_path=Path("tiny.py"), code="x")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the module
    codeflash_output = get_optimized_code_for_module(Path("tiny.py"), optimized_code); result = codeflash_output # 14.6μs -> 15.4μs (5.15% slower)

def test_large_number_of_code_strings():
    """Test performance with a large number of code strings."""
    # Create 1000 code strings
    code_strings = [
        CodeString(file_path=Path(f"module_{i}.py"), code=f"code_{i}")
        for i in range(1000)
    ]
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Query for a module in the middle of the list
    codeflash_output = get_optimized_code_for_module(Path("module_500.py"), optimized_code); result = codeflash_output # 791μs -> 813μs (2.66% slower)

def test_large_code_string_with_complex_nested_paths():
    """Test that large code strings with deeply nested paths work correctly."""
    # Create a deeply nested path with large code
    nested_path = Path("a/b/c/d/e/f/g/h/i/j/module.py")
    large_code = "def " + "nested_" * 1000 + "function(): pass"
    code_string = CodeString(file_path=nested_path, code=large_code)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query for the nested module
    codeflash_output = get_optimized_code_for_module(nested_path, optimized_code); result = codeflash_output # 13.2μs -> 14.2μs (6.76% slower)

def test_many_code_strings_with_similar_paths():
    """Test with many code strings having similar but distinct paths."""
    # Create 500 code strings with similar paths
    code_strings = [
        CodeString(file_path=Path(f"package/module/submodule_{i}/file.py"), code=f"code_{i}")
        for i in range(500)
    ]
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Query for a specific module
    codeflash_output = get_optimized_code_for_module(Path("package/module/submodule_250/file.py"), optimized_code); result = codeflash_output # 458μs -> 467μs (1.99% slower)

def test_caching_behavior_with_multiple_queries():
    """Test that the file_to_path caching works correctly across multiple queries."""
    # Create multiple code strings
    code_strings = [
        CodeString(file_path=Path(f"module_{i}.py"), code=f"code_{i}")
        for i in range(100)
    ]
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Perform multiple queries on the same optimized_code instance
    results = [
        get_optimized_code_for_module(Path(f"module_{i}.py"), optimized_code)
        for i in range(100)
    ]
    
    # Verify all queries return correct results
    for i, result in enumerate(results):
        pass
    
    # Verify cache was used (should be same dict instance)
    cache_1 = optimized_code.file_to_path()
    cache_2 = optimized_code.file_to_path()

def test_large_number_of_queries_on_same_instance():
    """Test performance with many repeated queries on the same CodeStringsMarkdown."""
    # Create a CodeStringsMarkdown with multiple code strings
    code_strings = [
        CodeString(file_path=Path(f"module_{i}.py"), code=f"code_{i}")
        for i in range(50)
    ]
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Perform 1000 queries
    for _ in range(1000):
        codeflash_output = get_optimized_code_for_module(Path("module_25.py"), optimized_code); result = codeflash_output # 4.35ms -> 2.90ms (49.8% faster)

def test_stress_test_varied_code_sizes():
    """Test with a large number of code strings of varying sizes."""
    # Create code strings with exponentially increasing code sizes
    code_strings = []
    for i in range(100):
        code = "x = 1\n" * (2 ** (i % 10))  # Code size varies from 1 to 512 lines
        code_strings.append(CodeString(file_path=Path(f"module_{i}.py"), code=code))
    
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Query for a module with large code
    codeflash_output = get_optimized_code_for_module(Path("module_50.py"), optimized_code); result = codeflash_output # 96.1μs -> 100μs (4.65% slower)

def test_all_paths_none_fallback_single():
    """Test fallback when all paths are None but there is only one code string."""
    # Create a single code string with None path
    code_string = CodeString(file_path=None, code="universal_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with any path
    codeflash_output = get_optimized_code_for_module(Path("any_path.py"), optimized_code); result = codeflash_output # 21.3μs -> 15.0μs (41.8% faster)

def test_mixed_none_and_valid_paths_no_fallback():
    """Test that multiple code strings with mix of None and valid paths don't trigger fallback."""
    # Create multiple code strings with mix of None and valid paths
    code_strings = [
        CodeString(file_path=None, code="none_code_1"),
        CodeString(file_path=Path("module_a.py"), code="code_a"),
        CodeString(file_path=None, code="none_code_2"),
    ]
    optimized_code = CodeStringsMarkdown(code_strings=code_strings)
    
    # Query with a path that doesn't match
    codeflash_output = get_optimized_code_for_module(Path("nonexistent.py"), optimized_code); result = codeflash_output # 1.51ms -> 1.47ms (2.44% faster)

def test_complex_path_normalization():
    """Test that Path objects normalize paths correctly before string conversion."""
    # Create code strings with paths that normalize to the same value
    code_string = CodeString(file_path=Path("./module.py"), code="normalized_code")
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Query with a path that should normalize the same way
    codeflash_output = get_optimized_code_for_module(Path("./module.py"), optimized_code); result = codeflash_output # 14.3μs -> 15.5μs (7.26% slower)

def test_performance_with_repeated_fallback_queries():
    """Test performance when repeatedly querying with fallback scenario."""
    # Create a single code string with None path
    code_string = CodeString(file_path=None, code="fallback_code_" * 100)
    optimized_code = CodeStringsMarkdown(code_strings=[code_string])
    
    # Perform 1000 queries that trigger fallback
    for _ in range(1000):
        codeflash_output = get_optimized_code_for_module(Path("random_path.py"), optimized_code); result = codeflash_output # 5.87ms -> 3.11ms (88.9% 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-pr1717-2026-03-02T18.58.47 and push.

Codeflash Static Badge

HeshamHM28 and others added 30 commits February 12, 2026 19:38
…tion

Two more instrumentation bugs:

1. Class renaming only updated the `class` declaration line, leaving
   return types, constructors, and other self-references unchanged.
   When the class has a method like `public OriginalClass of(...)
   { return this; }`, the renamed `this` no longer matches the
   unrenamed return type. Fixed by replacing ALL word-boundary-
   matched occurrences of the original class name throughout the
   entire source, not just in the class declaration.

2. Captured result variables (`var _cf_result8_2 = ...`) were
   declared inside nested blocks (while/for/try) but the
   serialization line referencing them was placed at the end of
   the method body, outside the block scope. Java block scoping
   makes the variable invisible there. Fixed by serializing
   immediately after each capture, while the variable is still
   in scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The lambda detection regex only matched no-arg lambdas `() -> {`
but missed parameterized lambdas like `(a, b, c) -> {`. This caused
instrumentation to insert `_cf_serializedResult` assignments inside
lambda bodies, violating Java's effectively-final requirement for
captured variables.

Broadened the block lambda detection from `\(\s*\)\s*->\s*\{` to
`->\s*\{`, and the expression lambda detection from `\(\s*\)\s*->`
to `->\s+\S`. This correctly detects all lambda forms and skips
instrumenting calls inside them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eout-and-test-categorization

fix: Java line profiler timeout and test categorization
The 120-second Maven timeout was only applied when test_framework ==
"junit5", leaving junit4 and testng with the default 15-second Python
pytest timeout. This caused Maven performance tests to always time out
on the first loop (Maven needs ~38s just to compile), resulting in
"best of 1 runs" benchmarks with unreliable results.

Change the condition to apply the longer timeout for all Java test
frameworks: junit4, junit5, and testng. Both the behavioral test runner
and the benchmarking test runner are fixed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rations

The line profiler's class detection only checked for "public class " or
"class " prefixes, failing to match declarations with additional modifiers
like "public final class". This caused the profiler class to be inserted
before the package statement (at index 0), producing illegal Java code.

Use a regex pattern that handles any combination of Java modifiers
(public, private, protected, final, abstract, static, sealed, non-sealed)
before class/interface/enum/record declarations.

Also removed an unused variable (instrumented_source) that was computed
but never referenced.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two fixes:

1. Line profiler class detection: The regex only matched "public class" or
   "class" prefixes, failing on declarations with modifiers like
   "public final class". Use a regex that handles any combination of Java
   modifiers before class/interface/enum/record declarations.

2. Line profiler timeout: The dispatcher passed INDIVIDUAL_TESTCASE_TIMEOUT
   (15s) directly to the Java line profiler test runner, which used
   `timeout or 120` (truthy 15 doesn't trigger the 120s fallback).
   Apply JAVA_TESTCASE_TIMEOUT consistently for all Java test phases,
   and use max() instead of `or` for the Java default timeout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tern

Same bug as the line profiler timeout: `timeout or max(120, ...)` doesn't
trigger the fallback when timeout is a truthy low value like 15.
Use max() to ensure Maven always gets at least 120 seconds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…imeout

The upstream omni-java branch already implemented a cleaner version of the
line profiler timeout fix (with min_timeout variable and debug logging).
Keep their version since it achieves the same goal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t-guard

fix(java): fix Java instrumentation, JPMS, and timeout bugs for QuestDB
## Changes

### Debug Logging Added
- parse_test_output.py: Added [RESOLVE], [PARSE-XML] logs for test file resolution
- function_optimizer.py: Added [JAVA-ROOT], [WRITE-PATH], [REGISTER] logs
- Traces complete flow from test generation → writing → registration → execution → parsing

### Bug Fixes
1. function_optimizer.py (lines 1855-1877): Fixed missing test_string parameter
   - Read test file content before passing to instrument_existing_test()
   - Pass test_string with test_path as optional parameter

2. java/support.py (lines 294-296): Fixed incorrect parameters in wrapper
   - Use named parameters matching new instrument_existing_test() signature
   - Removed obsolete call_positions, tests_project_root, analyzer parameters

## Testing
- Added debug logs confirmed working in Fibonacci optimization
- Test files written to correct locations with proper instrumentation
- TestFile registry contains accurate paths
- Ready for aerospike-client-java validation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…tures

Enhanced _get_java_sources_root() to handle projects where tests_root points
to a module directory that contains a 'src' subdirectory (e.g., test/src).

Added checks for:
1. tests_root already ending with "src" (already a sources root)
2. Simple "src" subdirectory before checking Maven-standard src/test/java

This fixes the base_dir mismatch bug where tests were written to the wrong
directory in multi-module Maven projects like aerospike-client-java.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…e-dir-mismatch

fix: Java behavior test execution in multi-module Maven projects
In --all mode, stale line numbers in FunctionToOptimize caused
InvalidJavaSyntaxError when a prior optimization modified the same file.
Now extract_function_source re-parses with tree-sitter to find methods
by name, matching how Python (jedi) and Java replacement already work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s-all-mode

fix: use tree-sitter name-based lookup for Java function extraction
KRRT7 and others added 21 commits March 2, 2026 08:59
…ns from tests

- Implement add_global_declarations for JavaSupport to insert new class
  fields and helper methods from optimized code before function replacement
- Remove inner_iterations kwarg from test_run_and_parse.py (removed from
  run_and_parse_tests in main), use CODEFLASH_INNER_ITERATIONS env var instead
…ks with protocol

- Add test_string param to PythonSupport.instrument_existing_test and
  pass it from function_optimizer (fixes inject_profiling_into_existing_test
  missing arg error)
- Add adjust_test_config_for_discovery to JavaSupport (sets
  tests_project_rootdir = tests_root)
- Fix discover_functions calls in test_support.py and test_integration.py
  to use (source, file_path) protocol signature
- Remove stale is_python mock in test_java_tests_project_rootdir.py
  (set_current_language already handles routing)
- Fix test_java_e2e.py to use Java context extraction instead of Python's
The merge from main removed the is_java() branch in
resolve_test_file_from_class_path that converts Java class paths
(com.example.TestClass) to file paths (com/example/TestClass.java).
Without it, JUnit XML parsing can't find instrumented test files.
Java needs prepare_module to return ValidCode without AST parsing,
same as JavaScript. Without it, the optimizer skips all Java functions
with "preparation error".
The merge from main stripped ~270 lines of Java-specific parsing logic
from parse_test_output.py including:
- Java test file resolution from class paths
- Java timing marker parsing (5-field format vs Python's 6-field)
- Java fallback stdout parsing for JUnit Console Launcher
- Java SQLite result handling with Gson serialization
- JaCoCo coverage loading
- Java performance stdout preservation

Restored the omni-java version which has all Java support intact
alongside the existing Python and JS parsing.
…egression fixes

- Create JavaFunctionOptimizer with get_code_optimization_context and
  replace_function_and_helpers_with_optimized_code (fixes NotImplementedError
  crash in java-fibonacci CI)
- Add function_optimizer_class and process_generated_test_strings to JavaSupport
- Fix missing testing_type param in parse_test_results call
- Fix Java existing test path suffix mismatch (__perfinstrumented →
  __existing_perfinstrumented)
- Clean up stale SQLite files in test_behavior_mode_writes_to_sqlite
… runner

The Java runner was always overriding CODEFLASH_INNER_ITERATIONS with its
default parameter (10), clobbering the value set by callers via test_env.
Now only sets the default when test_env doesn't already provide it.
The optimization replaces an `if "key" in dict` check followed by a separate `dict[key]` access in `file_to_path()` with a single try/except on KeyError, halving the dictionary operations in the 99% cache-hit path (from ~47% + 38% profiler time to ~71% in one lookup). It also guards two expensive logger calls—one constructing a large f-string with the entire `optimized_code` object—behind `isEnabledFor(DEBUG/WARNING)` checks, preventing format-string evaluation when logging is disabled. Line profiler shows the warning path dropped from 65.6% to 74.8% of total time, but because it fires on only 18 of 3136 calls the overall function runtime improved 13%, dominated by the dictionary micro-optimization on the hot cache-hit loop.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Mar 2, 2026
@claude
Copy link
Contributor

claude bot commented Mar 2, 2026

Duplicate Code Detection Results

Found 5 duplicates that should be consolidated:


1. escapeJson() method (HIGH confidence)

Locations:

  • codeflash-java-runtime/src/main/java/com/codeflash/Comparator.java:214
  • codeflash-java-runtime/src/main/java/com/codeflash/profiler/ProfilerReporter.java:84

What's duplicated: Identical 7-line JSON string escaping function that handles backslashes, quotes, and control characters.

Suggestion: Extract to a shared utility class (e.g., JsonUtils.java) within the codeflash-java-runtime package. Both classes should import from this common location.


2. remove_test_functions_from_generated_tests() (HIGH confidence)

Locations:

  • codeflash/languages/java/support.py:331-349
  • codeflash/languages/javascript/support.py:1768-1787

What's duplicated: Identical 18-line method that iterates over generated tests, removes specified functions, and rebuilds the GeneratedTestsList.

Suggestion: Extract to languages/base.py as a default implementation or create a shared mixin. Both Java and JavaScript implementations are byte-for-byte identical except for whitespace.


3. add_runtime_comments_to_generated_tests() (HIGH confidence)

Locations:

  • codeflash/languages/java/support.py:351-377
  • codeflash/languages/javascript/support.py:1789-1817

What's duplicated: Nearly identical 26-line method that builds runtime maps and adds performance comments to generated tests. Only difference is JavaScript version passes tests_project_rootdir to _build_runtime_map().

Suggestion: Extract to a base class or shared utility. The minor difference in _build_runtime_map() signature can be handled via method overriding.


4. _build_runtime_map() (MEDIUM confidence)

Locations:

  • codeflash/languages/java/support.py:379-398
  • codeflash/languages/javascript/support.py:1829-1850

What's duplicated: Core logic for building test invocation ID → runtime mapping is ~80% identical. Both construct qualified names, parse iteration IDs, and aggregate runtimes. JavaScript version has additional path resolution logic.

Suggestion: Extract shared logic to base class. JavaScript can override to add its path-specific handling while inheriting the common qualified name and iteration parsing logic.


5. Java build tool detection (MEDIUM confidence)

Locations:

  • codeflash/languages/java/support.py:434-440 (get_project_root())
  • codeflash/cli_cmds/cli.py:335-338
  • codeflash/cli_cmds/init_java.py:67-70 (detect_java_build_tool())
  • codeflash/languages/java/build_tools.py:94-99 (detect_build_tool())
  • codeflash/setup/detector.py:204-210
  • codeflash/cli_cmds/cmd_init.py:1267-1268

What's duplicated: Logic that checks for pom.xml, build.gradle, or build.gradle.kts to identify Maven/Gradle projects. Pattern appears in 6+ locations.

Suggestion: Consolidate into languages/java/build_tools.py (which already has detect_build_tool()). Other modules should import from there instead of re-implementing. Note: Some usage is for project root finding vs build tool identification — consider whether these should be separate utilities.


Summary:

  • Items 1-4 are clear-cut duplicates suitable for immediate consolidation
  • Item 5 is a repeated pattern that warrants centralization but may require more careful refactoring due to its widespread use across initialization and detection code

@KRRT7 KRRT7 force-pushed the prepare-java-support-2 branch 2 times, most recently from 7f96d61 to 7b8169d Compare March 2, 2026 19:13
@codeflash-ai codeflash-ai bot closed this Mar 2, 2026
@codeflash-ai
Copy link
Contributor Author

codeflash-ai bot commented Mar 2, 2026

This PR has been automatically closed because the original PR #1717 by KRRT7 was closed.

@codeflash-ai codeflash-ai bot deleted the codeflash/optimize-pr1717-2026-03-02T18.58.47 branch March 2, 2026 19:53
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.

6 participants