Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Dec 14, 2025

⚡️ This pull request contains optimizations for PR #970

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

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


📄 2,062% (20.62x) speedup for FunctionRanker.get_function_stats_summary in codeflash/benchmarking/function_ranker.py

⏱️ Runtime : 1.48 milliseconds 68.6 microseconds (best of 115 runs)

📝 Explanation and details

The optimization replaces an O(N) linear search through all functions with an O(1) hash table lookup followed by iteration over only matching function names.

Key Changes:

  • Added _function_stats_by_name index in __init__ that maps function names to lists of (key, stats) tuples
  • Modified get_function_stats_summary to first lookup candidates by function name, then iterate only over those candidates

Why This is Faster:
The original code iterates through ALL function stats (22,603 iterations in the profiler results) for every lookup. The optimized version uses a hash table to instantly find only the functions with matching names, then iterates through just those candidates (typically 1-2 functions).

Performance Impact:

  • Small datasets: 15-30% speedup as shown in basic test cases
  • Large datasets: Dramatic improvement - the test_large_scale_performance case with 900 functions shows 3085% speedup (66.7μs → 2.09μs)
  • Overall benchmark: 2061% speedup demonstrates the optimization scales excellently with dataset size

When This Optimization Shines:

  • Large codebases with many profiled functions (where the linear search becomes expensive)
  • Repeated function lookups (if this method is called frequently)
  • Cases with many unique function names but few duplicates per name

The optimization maintains identical behavior while transforming the algorithm from O(N) per lookup to O(average functions per name) per lookup, which is typically O(1) in practice.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 40 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from pathlib import Path

# imports


# function to test
# (The FunctionRanker class is defined above.)

# --- Helper Classes and Functions ---


class DummyLogger:
    """A dummy logger to replace the real logger for testing."""

    def debug(self, msg):
        pass

    def warning(self, msg):
        pass


class DummyProfileStats:
    """A dummy ProfileStats to inject profiling stats for testing."""

    def __init__(self, stats):
        self.stats = stats


class DummyFunctionToOptimize:
    """A simple stand-in for FunctionToOptimize."""

    def __init__(self, function_name, file_path):
        self.function_name = function_name
        self.file_path = Path(file_path)


# Patch the FunctionRanker to inject dummy stats and logger
def make_ranker_with_stats(stats_dict):
    # Patch logger and ProfileStats
    import codeflash.benchmarking.function_ranker as fr

    fr.logger = DummyLogger()
    fr.ProfileStats = lambda _: DummyProfileStats(stats_dict)
    # Patch is_pytest_infrastructure to always return False
    fr.is_pytest_infrastructure = lambda filename, func_name: False
    # Create FunctionRanker with dummy trace path
    return fr.FunctionRanker(Path("dummy/path/trace.prof"))


# --- Basic Test Cases ---


def test_basic_multiple_functions():
    """Test with multiple functions, only one matches."""
    stats = {
        ("foo.py", 10, "my_func"): (2, 1, 200, 300, {}),
        ("foo.py", 20, "other_func"): (3, 1, 300, 400, {}),
        ("bar.py", 5, "my_func"): (1, 1, 100, 120, {}),
    }
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("my_func", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 2.18μs -> 1.89μs (15.3% faster)


def test_basic_function_name_collision():
    """Test with two functions of same name in different files."""
    stats = {("foo.py", 10, "dup_func"): (1, 1, 10, 15, {}), ("bar.py", 20, "dup_func"): (2, 1, 20, 30, {})}
    ranker = make_ranker_with_stats(stats)
    func_foo = DummyFunctionToOptimize("dup_func", "foo.py")
    func_bar = DummyFunctionToOptimize("dup_func", "bar.py")
    codeflash_output = ranker.get_function_stats_summary(func_foo)
    summary_foo = codeflash_output  # 2.17μs -> 1.75μs (24.0% faster)
    codeflash_output = ranker.get_function_stats_summary(func_bar)
    summary_bar = codeflash_output  # 1.41μs -> 1.07μs (31.8% faster)


# --- Edge Test Cases ---


def test_edge_function_not_found():
    """Test when the function is not present in stats."""
    stats = {("foo.py", 10, "func_a"): (1, 1, 10, 15, {})}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("missing_func", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 2.05μs -> 1.59μs (28.9% faster)


def test_edge_empty_stats():
    """Test with empty stats dict."""
    stats = {}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("any_func", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 1.60μs -> 1.38μs (16.0% faster)


def test_edge_zero_call_count():
    """Test that functions with zero call_count are skipped."""
    stats = {("foo.py", 10, "func_a"): (0, 1, 0, 0, {}), ("foo.py", 20, "func_b"): (3, 1, 30, 45, {})}
    ranker = make_ranker_with_stats(stats)
    func_a = DummyFunctionToOptimize("func_a", "foo.py")
    func_b = DummyFunctionToOptimize("func_b", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func_a)
    summary_a = codeflash_output  # 1.88μs -> 1.44μs (30.5% faster)
    codeflash_output = ranker.get_function_stats_summary(func_b)
    summary_b = codeflash_output  # 1.31μs -> 1.30μs (0.768% faster)


def test_edge_function_in_subdirectory():
    """Test matching when file is in a subdirectory."""
    stats = {("src/foo.py", 10, "func_c"): (1, 1, 10, 20, {})}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("func_c", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 2.15μs -> 1.82μs (18.1% faster)


def test_edge_function_with_dot_in_name():
    """Test function names with dots but not class methods."""
    stats = {("foo.py", 10, "func.with.dot"): (2, 1, 20, 30, {})}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("func.with.dot", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 1.94μs -> 1.52μs (27.7% faster)


def test_edge_function_name_partial_match():
    """Test that partial matches do not return results."""
    stats = {("foo.py", 10, "my_func_special"): (1, 1, 10, 15, {})}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("my_func", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 1.89μs -> 1.45μs (30.4% faster)


def test_edge_multiple_functions_same_file():
    """Test with multiple functions of same name in same file."""
    stats = {("foo.py", 10, "func_x"): (1, 1, 10, 15, {}), ("foo.py", 20, "func_x"): (2, 1, 20, 30, {})}
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("func_x", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 2.15μs -> 1.91μs (12.6% faster)


# --- Large Scale Test Cases ---


def test_large_scale_collision_and_uniqueness():
    """Test with many functions with same name but different files."""
    stats = {}
    for i in range(300):
        stats[(f"dir_{i}/foo.py", 10, "common_func")] = (i + 2, 1, 50 + i, 100 + i, {})
    ranker = make_ranker_with_stats(stats)
    # Each file should match only its own version
    for i in [0, 50, 299]:
        func = DummyFunctionToOptimize("common_func", "foo.py")
        # Should match any with foo.py in key
        codeflash_output = ranker.get_function_stats_summary(func)
        summary = codeflash_output  # 4.16μs -> 3.74μs (11.3% faster)


def test_large_scale_performance():
    """Test that function works efficiently with large stats."""
    stats = {}
    for i in range(900):
        stats[("foo.py", i, f"func_{i}")] = (i + 1, 1, 100 + i, 200 + i, {})
    ranker = make_ranker_with_stats(stats)
    func = DummyFunctionToOptimize("func_899", "foo.py")
    codeflash_output = ranker.get_function_stats_summary(func)
    summary = codeflash_output  # 66.7μs -> 2.09μs (3085% faster)

To edit these changes git checkout codeflash/optimize-pr970-2025-12-14T17.16.41 and push.

Codeflash Static Badge

The optimization replaces an O(N) linear search through all functions with an O(1) hash table lookup followed by iteration over only matching function names.

**Key Changes:**
- Added `_function_stats_by_name` index in `__init__` that maps function names to lists of (key, stats) tuples
- Modified `get_function_stats_summary` to first lookup candidates by function name, then iterate only over those candidates

**Why This is Faster:**
The original code iterates through ALL function stats (22,603 iterations in the profiler results) for every lookup. The optimized version uses a hash table to instantly find only the functions with matching names, then iterates through just those candidates (typically 1-2 functions).

**Performance Impact:**
- **Small datasets**: 15-30% speedup as shown in basic test cases
- **Large datasets**: Dramatic improvement - the `test_large_scale_performance` case with 900 functions shows **3085% speedup** (66.7μs → 2.09μs)
- **Overall benchmark**: 2061% speedup demonstrates the optimization scales excellently with dataset size

**When This Optimization Shines:**
- Large codebases with many profiled functions (where the linear search becomes expensive)
- Repeated function lookups (if this method is called frequently)
- Cases with many unique function names but few duplicates per name

The optimization maintains identical behavior while transforming the algorithm from O(N) per lookup to O(average functions per name) per lookup, which is typically O(1) in practice.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Dec 14, 2025
@codeflash-ai codeflash-ai bot mentioned this pull request Dec 14, 2025
@KRRT7 KRRT7 merged commit e0d8900 into ranking-changes Dec 14, 2025
20 of 23 checks passed
@KRRT7 KRRT7 deleted the codeflash/optimize-pr970-2025-12-14T17.16.41 branch December 14, 2025 17:19
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