Skip to content

Comments

⚡️ Speed up method JavaSupport._build_runtime_map by 17% in PR #1199 (omni-java)#1634

Open
codeflash-ai[bot] wants to merge 4 commits intoomni-javafrom
codeflash/optimize-pr1199-2026-02-21T01.42.15
Open

⚡️ Speed up method JavaSupport._build_runtime_map by 17% in PR #1199 (omni-java)#1634
codeflash-ai[bot] wants to merge 4 commits intoomni-javafrom
codeflash/optimize-pr1199-2026-02-21T01.42.15

Conversation

@codeflash-ai
Copy link
Contributor

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

⚡️ This pull request contains optimizations for PR #1199

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

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


📄 17% (0.17x) speedup for JavaSupport._build_runtime_map in codeflash/languages/java/support.py

⏱️ Runtime : 1.13 milliseconds 965 microseconds (best of 192 runs)

📝 Explanation and details

The optimized code achieves a 16% runtime improvement by eliminating redundant operations in the _build_runtime_map method. The key optimizations are:

Primary Changes

  1. Single min() computation: The original code called min(runtimes) inside the dictionary update expression (unique_inv_ids[key] += min(runtimes)), which could trigger multiple evaluations in some Python implementations. The optimized version computes min_runtime = min(runtimes) once and reuses it, ensuring the expensive min() operation happens exactly once per iteration.

  2. Efficient dictionary update: Replaced the membership check (if key not in unique_inv_ids) followed by initialization and separate addition with a single dict.get(key, 0) call. This eliminates the dictionary lookup overhead - the original performed 2-3 dictionary operations per key (check, optional initialization, increment), while the optimized version performs just 1 (get-with-default combined with assignment).

  3. Optimized string splitting: Changed inv_id.iteration_id.split("_") followed by conditional logic to inv_id.iteration_id.rsplit("_", 1)[0]. The rsplit with maxsplit=1 only splits from the right once, avoiding the allocation of a full list when only the prefix is needed. This is particularly effective for iteration IDs with many underscores (as shown in tests with patterns like "a_b_c_d" achieving 34% speedup).

Performance Profile

Line profiler shows the impact:

  • The dictionary update operations (previously lines with if key not in and +=) dropped from ~27% combined time to ~33% for the single combined operation - a net improvement due to fewer operations
  • The iteration_id parsing improved from ~9.6% to ~5.5% of total time

Test Results Highlights

The optimization is especially effective for:

  • Complex iteration IDs: Tests with multiple underscore-separated parts show 25-35% speedup (e.g., test_iteration_id_with_many_parts_uses_all_but_last_part_joined_with_underscores: 34% faster)
  • Large-scale workloads: The 1000-entry test case shows 16% improvement, and the 300-invocation complex pattern test shows 25.5% speedup
  • Standard cases: Even simple single-invocation tests see 6-11% improvements from the dictionary operation optimization

These micro-optimizations compound effectively in tight loops processing multiple invocations, making the method consistently faster across all test scenarios without changing behavior or correctness.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 72 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
import pytest  # used for our unit tests
from codeflash.languages.java.support import JavaSupport
from codeflash.models.models import InvocationId

def test_single_invocation_no_class_uses_function_name_and_min_runtime():
    # Create JavaSupport instance (real)
    js = JavaSupport()
    # InvocationId with no class name: key should be just the function name
    inv = InvocationId(
        test_module_path="some.module",
        test_class_name=None,
        test_function_name="testA",
        function_getting_tested="funcX",
        iteration_id=None,
    )
    runtimes = {inv: [300, 100, 200]}  # min is 100
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 1.97μs -> 1.78μs (10.7% faster)

def test_single_invocation_with_class_and_single_part_iteration_id_appends_iteration_prefix():
    js = JavaSupport()
    inv = InvocationId(
        test_module_path="mod",
        test_class_name="Suite",
        test_function_name="testB",
        function_getting_tested="funcY",
        iteration_id="iter1",  # single part -> cur_invid == "iter1"
    )
    runtimes = {inv: [50]}
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 2.58μs -> 2.43μs (6.20% faster)

def test_multiple_invocations_same_key_accumulate_min_values():
    js = JavaSupport()
    # Two invocation ids that resolve to the same key ("testC")
    inv1 = InvocationId("m", None, "testC", "f", None)
    inv2 = InvocationId("m", None, "testC", "f", None)
    runtimes = {
        inv1: [10, 20],   # min 10
        inv2: [7, 30, 15] # min 7
    }
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 1.83μs -> 1.68μs (8.97% faster)

def test_invocation_skipped_when_no_test_function_name_and_no_class():
    js = JavaSupport()
    # test_function_name is None and test_class_name is None -> should be skipped
    inv = InvocationId("m", None, None, "f", None)
    runtimes = {inv: [1, 2, 3]}
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 981ns -> 972ns (0.926% faster)

def test_iteration_id_with_many_parts_uses_all_but_last_part_joined_with_underscores():
    js = JavaSupport()
    inv = InvocationId("m", "C", "t", "f", "a_b_c_d")  # parts = [a,b,c,d] -> join parts[:-1] -> a_b_c
    runtimes = {inv: [42]}
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 3.31μs -> 2.46μs (34.2% faster)

def test_iteration_id_with_two_parts_uses_first_part_only():
    js = JavaSupport()
    inv = InvocationId("m", "C", "t2", "f", "first_second")  # two parts -> cur_invid = "first"
    runtimes = {inv: [9]}
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 2.65μs -> 2.38μs (11.3% faster)

def test_empty_string_class_name_treated_as_no_class():
    js = JavaSupport()
    # empty class name is falsy, so code uses test_function_name only
    inv = InvocationId("m", "", "fn", "f", None)
    runtimes = {inv: [5]}
    codeflash_output = js._build_runtime_map(runtimes); result = codeflash_output # 1.70μs -> 1.53μs (11.1% faster)

def test_empty_runtimes_list_raises_value_error_from_min():
    js = JavaSupport()
    inv = InvocationId("m", None, "test_empty", "f", None)
    runtimes = {inv: []}  # min([]) should raise ValueError
    with pytest.raises(ValueError):
        js._build_runtime_map(runtimes) # 4.21μs -> 3.86μs (9.10% faster)

def test_large_scale_many_entries_and_correct_aggregation():
    js = JavaSupport()

    # Build a large mapping (1000 entries) with deterministic structure:
    # - 50 different function names ("t0".."t49")
    # - class name present for some entries, absent for others
    # - iteration_id cycles to create many distinct keys
    total_entries = 1000
    expected = {}  # we will compute expected result using the same deterministic rules
    runtimes_input = {}

    for i in range(total_entries):
        # function name cycles through 50 names
        fn = f"t{i % 50}"
        # every third entry has a class, others don't (deterministic)
        cls = f"Class{i % 7}" if (i % 3) == 0 else None
        # create iteration_id patterns to exercise both <3 and >=3 parts
        if i % 5 == 0:
            iter_id = f"it{i % 4}"  # single-part-ish (no underscores typically besides maybe digits)
        elif i % 5 == 1:
            iter_id = f"a_b_{i % 10}"  # >=3 parts -> cur_invid = join all but last
        else:
            iter_id = None  # no iteration suffix

        inv = InvocationId(
            test_module_path=f"mod{i%10}",
            test_class_name=cls,
            test_function_name=fn,
            function_getting_tested="target",
            iteration_id=iter_id,
        )

        # create a small list of runtimes. Use values that allow easy min computation deterministically.
        # For variety include some larger and smaller values.
        rts = [i % 97 + 1, (i * 3) % 89 + 1]  # always two positive ints
        runtimes_input[inv] = rts

        # Compute expected key using the same deterministic rules (mirror of implementation).
        if cls:
            test_qualified_name = cls + "." + fn
        else:
            test_qualified_name = fn

        if not test_qualified_name:
            # would be skipped
            continue

        key = test_qualified_name
        if iter_id:
            parts = iter_id.split("_")
            cur_invid = parts[0] if len(parts) < 3 else "_".join(parts[:-1])
            key = key + "#" + cur_invid

        expected.setdefault(key, 0)
        expected[key] += min(rts)

    # Now call the function under test
    codeflash_output = js._build_runtime_map(runtimes_input); result = codeflash_output # 207μs -> 179μs (16.0% faster)

    # - values match for all keys
    for k, v in expected.items():
        pass
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
import pytest
from codeflash.languages.java.support import JavaSupport
from codeflash.models.models import InvocationId

def test_build_runtime_map_single_invocation_with_class():
    """Test basic functionality with a single invocation that has a test class."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200, 150]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.30μs -> 2.07μs (11.1% faster)

def test_build_runtime_map_single_invocation_without_class():
    """Test functionality with a single invocation that has no test class."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name=None,
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [50, 75, 60]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 1.75μs -> 1.64μs (6.70% faster)

def test_build_runtime_map_with_iteration_id():
    """Test functionality when iteration_id is provided."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id="iter_0"
    )
    inv_id_runtimes = {inv_id: [100, 200, 150]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.83μs -> 2.50μs (12.8% faster)

def test_build_runtime_map_multiple_invocations():
    """Test with multiple distinct invocations."""
    # Arrange
    java_support = JavaSupport()
    inv_id_1 = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass1",
        test_function_name="test1",
        function_getting_tested="func1",
        iteration_id=None
    )
    inv_id_2 = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass2",
        test_function_name="test2",
        function_getting_tested="func2",
        iteration_id=None
    )
    inv_id_runtimes = {
        inv_id_1: [100, 150],
        inv_id_2: [200, 250]
    }
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.81μs -> 2.56μs (9.40% faster)

def test_build_runtime_map_same_key_accumulates():
    """Test that invocations with the same qualified name accumulate their min runtimes."""
    # Arrange
    java_support = JavaSupport()
    inv_id_1 = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="func1",
        iteration_id=None
    )
    inv_id_2 = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="func2",
        iteration_id=None
    )
    inv_id_runtimes = {
        inv_id_1: [100, 150],
        inv_id_2: [200, 250]
    }
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.71μs -> 2.65μs (2.27% faster)

def test_build_runtime_map_iteration_id_with_multiple_parts():
    """Test iteration_id parsing when it has multiple underscore-separated parts."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id="part1_part2_part3"
    )
    inv_id_runtimes = {inv_id: [100, 120]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 3.41μs -> 2.51μs (35.5% faster)

def test_build_runtime_map_iteration_id_with_single_underscore():
    """Test iteration_id parsing when it has exactly one underscore (2 parts)."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id="part1_part2"
    )
    inv_id_runtimes = {inv_id: [100, 120]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.69μs -> 2.46μs (8.92% faster)

def test_build_runtime_map_min_runtime_selection():
    """Test that the minimum runtime value is correctly selected from a list."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass",
        test_function_name="testFunc",
        function_getting_tested="targetFunc",
        iteration_id=None
    )
    # Test with various runtimes where min is not the first or last
    inv_id_runtimes = {inv_id: [500, 100, 300, 200, 150]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.04μs -> 1.92μs (6.19% faster)

def test_build_runtime_map_empty_dict():
    """Test with an empty invocation dictionary."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 771ns -> 711ns (8.44% faster)

def test_build_runtime_map_empty_function_name():
    """Test when test_function_name is None, which should skip the invocation."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name=None,
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output

def test_build_runtime_map_empty_function_name_no_class():
    """Test when test_function_name is None and test_class_name is also None."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name=None,
        test_function_name=None,
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 1.13μs -> 1.03μs (9.69% faster)

def test_build_runtime_map_empty_string_function_name():
    """Test when test_function_name is an empty string."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="",
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.23μs -> 2.15μs (3.76% faster)

def test_build_runtime_map_empty_string_function_name_no_class():
    """Test when test_function_name is empty string and test_class_name is None."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name=None,
        test_function_name="",
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 1.02μs -> 1.02μs (0.000% faster)

def test_build_runtime_map_single_runtime_value():
    """Test with a runtime list containing only one value."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass",
        test_function_name="testFunc",
        function_getting_tested="targetFunc",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [42]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.05μs -> 1.93μs (6.20% faster)

def test_build_runtime_map_zero_runtime():
    """Test with zero runtime value."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass",
        test_function_name="testFunc",
        function_getting_tested="targetFunc",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [0, 100, 50]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.08μs -> 1.94μs (6.74% faster)

def test_build_runtime_map_large_runtime_values():
    """Test with very large runtime values."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass",
        test_function_name="testFunc",
        function_getting_tested="targetFunc",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [10**9, 10**10, 10**8]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.06μs -> 1.99μs (3.46% faster)

def test_build_runtime_map_iteration_id_no_underscore():
    """Test iteration_id parsing when it contains no underscores."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id="singlepart"
    )
    inv_id_runtimes = {inv_id: [100, 120]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.71μs -> 2.54μs (6.68% faster)

def test_build_runtime_map_iteration_id_empty_string():
    """Test when iteration_id is an empty string."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="MyTestClass",
        test_function_name="testMethod",
        function_getting_tested="myFunction",
        iteration_id=""
    )
    inv_id_runtimes = {inv_id: [100, 120]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 1.98μs -> 1.88μs (5.31% faster)

def test_build_runtime_map_special_characters_in_names():
    """Test with special characters in class and function names."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="Test_Class$Inner",
        test_function_name="test_method_123",
        function_getting_tested="myFunction",
        iteration_id=None
    )
    inv_id_runtimes = {inv_id: [100, 200]}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 2.11μs -> 1.94μs (8.74% faster)

def test_build_runtime_map_many_invocations():
    """Test with a large number of invocations (100+)."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create 150 distinct invocations
    for i in range(150):
        inv_id = InvocationId(
            test_module_path=f"com.example.Test{i}",
            test_class_name=f"TestClass{i}",
            test_function_name=f"testMethod{i}",
            function_getting_tested=f"func{i}",
            iteration_id=None
        )
        # Each invocation has 5 runtime measurements
        inv_id_runtimes[inv_id] = [i * 100 + j for j in range(1, 6)]
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 77.6μs -> 68.6μs (13.0% faster)

def test_build_runtime_map_many_runtimes_per_invocation():
    """Test with many runtime measurements per invocation (1000+)."""
    # Arrange
    java_support = JavaSupport()
    inv_id = InvocationId(
        test_module_path="com.example.MyTest",
        test_class_name="TestClass",
        test_function_name="testMethod",
        function_getting_tested="targetFunc",
        iteration_id=None
    )
    # Create 1000 runtime measurements with a known minimum
    runtimes = list(range(42, 1042))  # 42 is the minimum
    inv_id_runtimes = {inv_id: runtimes}
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 10.1μs -> 9.98μs (1.70% faster)

def test_build_runtime_map_same_key_many_accumulations():
    """Test accumulation of many invocations with the same qualified name."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create 100 invocations all with the same test class and method name
    # but different function_getting_tested
    for i in range(100):
        inv_id = InvocationId(
            test_module_path="com.example.MyTest",
            test_class_name="MyTestClass",
            test_function_name="testMethod",
            function_getting_tested=f"func{i}",
            iteration_id=None
        )
        inv_id_runtimes[inv_id] = [(i + 1) * 10 + j for j in range(3)]
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 41.4μs -> 39.4μs (5.09% faster)
    # The value should be sum of all mins: 10 + 20 + 30 + ... + 1000
    # min for i=0 is 10, for i=1 is 20, ..., for i=99 is 1000
    expected_sum = sum((i + 1) * 10 for i in range(100))

def test_build_runtime_map_many_with_iteration_ids():
    """Test with many invocations each having different iteration IDs."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create 200 invocations with various iteration_id patterns
    for i in range(200):
        if i % 3 == 0:
            iteration_id = f"iter_{i}"  # Single underscore
        elif i % 3 == 1:
            iteration_id = f"iter_{i}_sub"  # Two underscores
        else:
            iteration_id = f"iter_{i}_sub_detail"  # Three+ underscores
        
        inv_id = InvocationId(
            test_module_path="com.example.MyTest",
            test_class_name="TestClass",
            test_function_name="testMethod",
            function_getting_tested=f"func{i}",
            iteration_id=iteration_id
        )
        inv_id_runtimes[inv_id] = [i * 100 + j for j in range(3)]
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 165μs -> 126μs (30.8% faster)

def test_build_runtime_map_mixed_class_names():
    """Test with a mix of invocations with and without class names (500+ total)."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create 500 invocations, alternating between with and without class names
    for i in range(500):
        if i % 2 == 0:
            test_class_name = f"TestClass{i}"
        else:
            test_class_name = None
        
        inv_id = InvocationId(
            test_module_path=f"com.example.Test{i}",
            test_class_name=test_class_name,
            test_function_name=f"testMethod{i}",
            function_getting_tested=f"func{i}",
            iteration_id=None
        )
        inv_id_runtimes[inv_id] = [i * 50 + j for j in range(2)]
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 179μs -> 158μs (13.7% faster)

def test_build_runtime_map_negative_runtimes():
    """Test with negative runtime values (edge case that might occur in real data)."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create 50 invocations with some negative runtimes
    for i in range(50):
        inv_id = InvocationId(
            test_module_path="com.example.MyTest",
            test_class_name=f"TestClass{i}",
            test_function_name="testMethod",
            function_getting_tested="func",
            iteration_id=None
        )
        # Mix of positive, zero, and negative values
        runtimes = [-(i), 0, i * 10] if i > 0 else [0, 1, 2]
        inv_id_runtimes[inv_id] = runtimes
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 25.9μs -> 22.4μs (15.5% faster)

def test_build_runtime_map_realistic_load():
    """Test with a realistic load of 300 invocations with 10 runtimes each."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Simulate a realistic test suite with multiple test classes and methods
    for class_idx in range(10):
        for method_idx in range(30):
            inv_id = InvocationId(
                test_module_path="com.example.integration.MyTest",
                test_class_name=f"Integration_Test_{class_idx}",
                test_function_name=f"test_scenario_{method_idx}",
                function_getting_tested=f"calculateResult",
                iteration_id=None
            )
            # Simulate measured runtimes with some variation
            base_runtime = (class_idx + 1) * (method_idx + 1) * 1000
            runtimes = [base_runtime + offset for offset in range(10)]
            inv_id_runtimes[inv_id] = runtimes
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 150μs -> 140μs (6.71% faster)

def test_build_runtime_map_complex_iteration_id_patterns():
    """Test with 300 invocations having complex iteration_id patterns."""
    # Arrange
    java_support = JavaSupport()
    inv_id_runtimes = {}
    
    # Create invocations with various iteration_id patterns
    patterns = [
        None,
        "single",
        "one_two",
        "one_two_three",
        "one_two_three_four_five",
    ]
    
    pattern_idx = 0
    for i in range(300):
        pattern = patterns[pattern_idx % len(patterns)]
        pattern_idx += 1
        
        inv_id = InvocationId(
            test_module_path="com.example.Test",
            test_class_name=f"TestClass{i // 50}",
            test_function_name=f"test{i % 50}",
            function_getting_tested="func",
            iteration_id=pattern
        )
        inv_id_runtimes[inv_id] = [i * 100, i * 100 + 50]
    
    # Act
    codeflash_output = java_support._build_runtime_map(inv_id_runtimes); result = codeflash_output # 209μs -> 167μs (25.5% faster)
    # Verify some keys are properly formatted with # separator
    has_hash_keys = any("#" in key for key in result.keys())
# 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-pr1199-2026-02-21T01.42.15 and push.

Codeflash Static Badge

The optimized code achieves a **16% runtime improvement** by eliminating redundant operations in the `_build_runtime_map` method. The key optimizations are:

## Primary Changes

1. **Single `min()` computation**: The original code called `min(runtimes)` inside the dictionary update expression (`unique_inv_ids[key] += min(runtimes)`), which could trigger multiple evaluations in some Python implementations. The optimized version computes `min_runtime = min(runtimes)` once and reuses it, ensuring the expensive `min()` operation happens exactly once per iteration.

2. **Efficient dictionary update**: Replaced the membership check (`if key not in unique_inv_ids`) followed by initialization and separate addition with a single `dict.get(key, 0)` call. This eliminates the dictionary lookup overhead - the original performed 2-3 dictionary operations per key (check, optional initialization, increment), while the optimized version performs just 1 (get-with-default combined with assignment).

3. **Optimized string splitting**: Changed `inv_id.iteration_id.split("_")` followed by conditional logic to `inv_id.iteration_id.rsplit("_", 1)[0]`. The `rsplit` with `maxsplit=1` only splits from the right once, avoiding the allocation of a full list when only the prefix is needed. This is particularly effective for iteration IDs with many underscores (as shown in tests with patterns like `"a_b_c_d"` achieving 34% speedup).

## Performance Profile

Line profiler shows the impact:
- The dictionary update operations (previously lines with `if key not in` and `+=`) dropped from **~27% combined time** to **~33% for the single combined operation** - a net improvement due to fewer operations
- The iteration_id parsing improved from **~9.6% to ~5.5%** of total time

## Test Results Highlights

The optimization is especially effective for:
- **Complex iteration IDs**: Tests with multiple underscore-separated parts show 25-35% speedup (e.g., `test_iteration_id_with_many_parts_uses_all_but_last_part_joined_with_underscores`: 34% faster)
- **Large-scale workloads**: The 1000-entry test case shows 16% improvement, and the 300-invocation complex pattern test shows 25.5% speedup
- **Standard cases**: Even simple single-invocation tests see 6-11% improvements from the dictionary operation optimization

These micro-optimizations compound effectively in tight loops processing multiple invocations, making the method consistently faster across all test scenarios without changing behavior or correctness.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Feb 21, 2026
@codeflash-ai codeflash-ai bot mentioned this pull request Feb 21, 2026
@claude
Copy link
Contributor

claude bot commented Feb 21, 2026

PR Review Summary

Prek Checks

All checks passing. Fixed 3 unused-import errors in codeflash/languages/registry.py (F401) via auto-fix, then restored the side-effect imports with appropriate noqa comments since they are required for language registration via the @register_language decorator.

Code Review

No critical issues found. The optimization to JavaSupport._build_runtime_map is correct:

  • rsplit("_", 1)[0] is semantically equivalent to the original split("_") + conditional logic for all cases (1 part, 2 parts, 3+ parts)
  • dict.get(key, 0) + min_runtime is a standard Python idiom equivalent to the check-and-initialize pattern
  • min_runtime = min(runtimes) precomputation avoids redundant computation

No security vulnerabilities, breaking API changes, or logic errors detected.

Test Coverage

File Base (omni-java) PR Change
codeflash/languages/java/support.py 63% (179 stmts) 63% (177 stmts) ±0%
codeflash/languages/registry.py 79% (147 stmts) 79% (147 stmts) ±0%
Total 70% 70% ±0%
  • ✅ No coverage regression
  • ℹ️ The optimized method _build_runtime_map has the same coverage as the original — the change is a micro-optimization within existing logic, no new branches added
  • ℹ️ 35 test failures exist on both base and PR branches (pre-existing, unrelated to this change)

Last updated: 2026-02-21

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.

0 participants