Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 26 additions & 31 deletions codeflash/code_utils/time_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,36 +53,31 @@ def humanize_runtime(time_in_ns: int) -> str:

def format_time(nanoseconds: int) -> str:
"""Format nanoseconds into a human-readable string with 3 significant digits when needed."""
# Inlined significant digit check: >= 3 digits if value >= 100
# Define conversion factors and units
conversions = [(1_000_000_000, "s"), (1_000_000, "ms"), (1_000, "μs"), (1, "ns")]

# Handle nanoseconds case directly (no decimal formatting needed)
if nanoseconds < 1_000:
return f"{nanoseconds}ns"
if nanoseconds < 1_000_000:
microseconds_int = nanoseconds // 1_000
if microseconds_int >= 100:
return f"{microseconds_int}μs"
microseconds = nanoseconds / 1_000
# Format with precision: 3 significant digits
if microseconds >= 100:
return f"{microseconds:.0f}μs"
if microseconds >= 10:
return f"{microseconds:.1f}μs"
return f"{microseconds:.2f}μs"
if nanoseconds < 1_000_000_000:
milliseconds_int = nanoseconds // 1_000_000
if milliseconds_int >= 100:
return f"{milliseconds_int}ms"
milliseconds = nanoseconds / 1_000_000
if milliseconds >= 100:
return f"{milliseconds:.0f}ms"
if milliseconds >= 10:
return f"{milliseconds:.1f}ms"
return f"{milliseconds:.2f}ms"
seconds_int = nanoseconds // 1_000_000_000
if seconds_int >= 100:
return f"{seconds_int}s"
seconds = nanoseconds / 1_000_000_000
if seconds >= 100:
return f"{seconds:.0f}s"
if seconds >= 10:
return f"{seconds:.1f}s"
return f"{seconds:.2f}s"

# Find appropriate unit
for divisor, unit in conversions:
if nanoseconds >= divisor:
value = nanoseconds / divisor
int_value = nanoseconds // divisor

# Use integer formatting for values >= 100
if int_value >= 100:
formatted_value = str(int_value)
# Format with precision for 3 significant digits
elif value >= 100:
formatted_value = f"{value:.0f}"
elif value >= 10:
formatted_value = f"{value:.1f}"
else:
formatted_value = f"{value:.2f}"

return f"{formatted_value}{unit}"

# This should never be reached, but included for completeness
return f"{nanoseconds}ns"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚡️Codeflash found 36% (0.36x) speedup for format_time in codeflash/code_utils/time_utils.py

⏱️ Runtime : 2.86 milliseconds 2.11 milliseconds (best of 130 runs)

📝 Explanation and details Here's a significantly **faster** version of your function. **Main bottlenecks:** - The `conversions` list is being recreated every call (move outside the function). - Division (and string formatting) is repeated unnecessarily. - For most inputs, only one conversion is needed, so using `elif` instead of a loop is faster. - Inlining the logic (removing the for loop) along with minimal branching is much faster. - Use `str()` formatting (not f-strings) for speed with integers.

Here's a rewritten, optimized version.

Optimization summary:

  • Conversion table is not reconstructed per call.
  • No loop; fastest matching unit is chosen via flat if.
  • Common case (<1000) is handled with a very fast path.
  • No extra work, all math and comparisons are minimal and streamlined.

Same output guaranteed, significantly faster runtime for all inputs.

Let me know if you want it further micro-optimized or vectorized!

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 6129 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 4 Passed
📊 Tests Coverage 87.5%
🌀 Generated Regression Tests Details
import pytest  # used for our unit tests
from codeflash.code_utils.time_utils import format_time

# unit tests

# -------------------------
# Basic Test Cases
# -------------------------

@pytest.mark.parametrize("nanoseconds,expected", [
    (0, "0ns"),                # zero nanoseconds
    (1, "1ns"),                # single nanosecond
    (999, "999ns"),            # just below 1μs
    (1_000, "1.00μs"),         # exactly 1μs
    (1_234, "1.23μs"),         # typical microseconds (2 decimal)
    (12_345, "12.3μs"),        # typical microseconds (1 decimal)
    (123_456, "123μs"),        # microseconds, integer formatting
    (1_000_000, "1.00ms"),     # exactly 1ms
    (1_234_567, "1.23ms"),     # typical milliseconds (2 decimal)
    (12_345_678, "12.3ms"),    # typical milliseconds (1 decimal)
    (123_456_789, "123ms"),    # milliseconds, integer formatting
    (1_000_000_000, "1.00s"),  # exactly 1 second
    (1_234_567_890, "1.23s"),  # seconds (2 decimal)
    (12_345_678_900, "12.3s"), # seconds (1 decimal)
    (123_456_789_000, "123s"), # seconds, integer formatting
])
def test_format_time_basic(nanoseconds, expected):
    """Test basic formatting for a variety of typical values."""
    codeflash_output = format_time(nanoseconds) # 831ns -> 681ns

# -------------------------
# Edge Test Cases
# -------------------------

def test_format_time_negative():
    """Test negative nanoseconds (should still format, though not specified)."""
    codeflash_output = format_time(-1) # 351ns -> 300ns
    codeflash_output = format_time(-999) # 351ns -> 300ns
    codeflash_output = format_time(-1_000) # 351ns -> 300ns
    codeflash_output = format_time(-1_234_567_890) # 351ns -> 300ns

@pytest.mark.parametrize("nanoseconds,expected", [
    (999, "999ns"),            # maximum ns before μs
    (1_000, "1.00μs"),         # minimum μs
    (999_999, "999μs"),        # maximum μs before ms
    (1_000_000, "1.00ms"),     # minimum ms
    (999_999_999, "999ms"),    # maximum ms before s
    (1_000_000_000, "1.00s"),  # minimum s
])
def test_format_time_unit_boundaries(nanoseconds, expected):
    """Test values exactly at the boundaries between units."""
    codeflash_output = format_time(nanoseconds) # 801ns -> 611ns

@pytest.mark.parametrize("nanoseconds,expected", [
    (100, "100ns"),              # exactly 100ns, should be integer
    (10_000, "10.0μs"),          # exactly 10μs, should be 1 decimal
    (100_000, "100μs"),          # exactly 100μs, should be integer
    (10_000_000, "10.0ms"),      # exactly 10ms, should be 1 decimal
    (100_000_000, "100ms"),      # exactly 100ms, should be integer
    (10_000_000_000, "10.0s"),   # exactly 10s, should be 1 decimal
    (100_000_000_000, "100s"),   # exactly 100s, should be integer
])
def test_format_time_significant_digit_cutoffs(nanoseconds, expected):
    """Test cutoffs for significant digit formatting."""
    codeflash_output = format_time(nanoseconds) # 842ns -> 642ns

def test_format_time_large_and_small_values():
    """Test very large and very small values."""
    # Very large value (trillions of ns)
    codeflash_output = format_time(1_000_000_000_000) # 641ns -> 531ns
    # Very small negative value
    codeflash_output = format_time(-999) # 641ns -> 531ns
    # Value just below a boundary
    codeflash_output = format_time(999_999) # 641ns -> 531ns
    # Value just above a boundary
    codeflash_output = format_time(1_000_001) # 641ns -> 531ns

def test_format_time_type_errors():
    """Test that non-integer input raises TypeError (if function is strict)."""
    # The current implementation does not raise, but we check for robustness.
    with pytest.raises(TypeError):
        format_time("1000")
    with pytest.raises(TypeError):
        format_time(None)
    with pytest.raises(TypeError):
        format_time(1.23)

# -------------------------
# Large Scale Test Cases
# -------------------------

def test_format_time_large_scale_uniform():
    """Test formatting for a large, uniform range of values."""
    # Test every 1_000_000_000 ns (1s) up to 999_000_000_000 ns (999s)
    for i in range(1, 1000):
        ns = i * 1_000_000_000
        expected = f"{i}s" if i >= 100 else f"{i:.2f}s" if i < 10 else f"{i:.1f}s"
        # The function only uses 2 decimals for <10, 1 decimal for <100, integer for >=100
        if i >= 100:
            expected = f"{i}s"
        elif i >= 10:
            expected = f"{i:.1f}s"
        else:
            expected = f"{i:.2f}s"
        codeflash_output = format_time(ns) # 440ns -> 310ns

def test_format_time_large_scale_varied_units():
    """Test formatting for a large list of values spanning all units."""
    # Build a list of representative values for each unit
    test_values = []
    expected_results = []
    # ns: 0-999
    for i in range(0, 1000, 100):
        test_values.append(i)
        expected_results.append(f"{i}ns")
    # μs: 1_000-999_999
    for i in range(1_000, 1_000_000, 100_000):
        val = i / 1_000
        if val >= 100:
            expected = f"{int(val)}μs"
        elif val >= 10:
            expected = f"{val:.1f}μs"
        else:
            expected = f"{val:.2f}μs"
        test_values.append(i)
        expected_results.append(expected)
    # ms: 1_000_000-999_999_999
    for i in range(1_000_000, 1_000_000_000, 100_000_000):
        val = i / 1_000_000
        if val >= 100:
            expected = f"{int(val)}ms"
        elif val >= 10:
            expected = f"{val:.1f}ms"
        else:
            expected = f"{val:.2f}ms"
        test_values.append(i)
        expected_results.append(expected)
    # s: 1_000_000_000-999_999_999_999
    for i in range(1_000_000_000, 1_000_000_000_000, 100_000_000_000):
        val = i / 1_000_000_000
        if val >= 100:
            expected = f"{int(val)}s"
        elif val >= 10:
            expected = f"{val:.1f}s"
        else:
            expected = f"{val:.2f}s"
        test_values.append(i)
        expected_results.append(expected)
    # Now test all
    for ns, expected in zip(test_values, expected_results):
        codeflash_output = format_time(ns) # 280ns -> 230ns

def test_format_time_performance_large_batch():
    """Performance: format a large batch of random values, ensure no error and correct format."""
    import random
    random.seed(42)
    values = [random.randint(0, 10**12) for _ in range(1000)]
    # Just check that the function returns a string and doesn't crash
    for ns in values:
        codeflash_output = format_time(ns); result = codeflash_output # 451ns -> 330ns
        # Should never have more than 2 decimals
        if '.' in result:
            decimals = result.split('.')[1]
            # Remove unit
            decimals = decimals.rstrip("nsμsms")
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import pytest  # used for our unit tests
from codeflash.code_utils.time_utils import format_time

# unit tests

# 1. Basic Test Cases

def test_ns_under_1000():
    # Test values less than 1000 ns
    codeflash_output = format_time(0) # 351ns -> 281ns
    codeflash_output = format_time(1) # 351ns -> 281ns
    codeflash_output = format_time(999) # 351ns -> 281ns

def test_exact_1000_ns():
    # Test exactly 1000 ns (should be 1.00μs)
    codeflash_output = format_time(1000) # 2.79μs -> 2.38μs

def test_microseconds_formatting():
    # Test values in microseconds range
    codeflash_output = format_time(1500) # 811ns -> 721ns
    codeflash_output = format_time(10_000) # 811ns -> 721ns
    codeflash_output = format_time(999_999) # 811ns -> 721ns

def test_exact_1_millisecond():
    # Test exactly 1 ms (1_000_000 ns)
    codeflash_output = format_time(1_000_000) # 2.46μs -> 2.11μs

def test_milliseconds_formatting():
    # Test values in milliseconds range
    codeflash_output = format_time(1_234_567) # 781ns -> 581ns
    codeflash_output = format_time(12_345_678) # 781ns -> 581ns
    codeflash_output = format_time(999_999_999) # 781ns -> 581ns

def test_exact_1_second():
    # Test exactly 1 second (1_000_000_000 ns)
    codeflash_output = format_time(1_000_000_000) # 2.36μs -> 2.08μs

def test_seconds_formatting():
    # Test values in seconds range
    codeflash_output = format_time(1_234_567_890) # 561ns -> 411ns
    codeflash_output = format_time(12_345_678_900) # 561ns -> 411ns
    codeflash_output = format_time(123_456_789_000) # 561ns -> 411ns
    codeflash_output = format_time(999_999_999_999) # 561ns -> 411ns

def test_rounding_behavior():
    # Test rounding for 3 significant digits
    codeflash_output = format_time(1_234) # 430ns -> 310ns
    codeflash_output = format_time(1_235) # 430ns -> 310ns
    codeflash_output = format_time(12_345) # 430ns -> 310ns
    codeflash_output = format_time(123_456) # 430ns -> 310ns
    codeflash_output = format_time(123_456_789) # 430ns -> 310ns
    codeflash_output = format_time(123_499_999) # 430ns -> 310ns
    codeflash_output = format_time(123_500_000) # 430ns -> 310ns

# 2. Edge Test Cases

def test_just_below_and_above_unit_boundaries():
    # Just below 1 μs
    codeflash_output = format_time(999) # 561ns -> 400ns
    # Exactly 1 μs
    codeflash_output = format_time(1000) # 561ns -> 400ns
    # Just above 1 μs
    codeflash_output = format_time(1001) # 561ns -> 400ns
    # Just below 1 ms
    codeflash_output = format_time(999_999) # 561ns -> 400ns
    # Exactly 1 ms
    codeflash_output = format_time(1_000_000) # 561ns -> 400ns
    # Just above 1 ms
    codeflash_output = format_time(1_000_001) # 561ns -> 400ns
    # Just below 1 s
    codeflash_output = format_time(999_999_999) # 561ns -> 400ns
    # Exactly 1 s
    codeflash_output = format_time(1_000_000_000) # 561ns -> 400ns
    # Just above 1 s
    codeflash_output = format_time(1_000_000_001) # 561ns -> 400ns

def test_large_integer_values():
    # Test large values, near the 32-bit and 64-bit integer boundaries
    codeflash_output = format_time(2_147_483_647) # 1.35μs -> 1.33μs
    codeflash_output = format_time(9_223_372_036_854_775_807) # 1.35μs -> 1.33μs

def test_smallest_nonzero_ns():
    # Test smallest nonzero value
    codeflash_output = format_time(1) # 771ns -> 601ns

def test_negative_value():
    # Negative values are not meaningful for time, but test for robustness
    # Should still format as ns, as per implementation
    codeflash_output = format_time(-1) # 350ns -> 290ns
    codeflash_output = format_time(-1000) # 350ns -> 290ns
    codeflash_output = format_time(-1_000_000) # 350ns -> 290ns
    codeflash_output = format_time(-1_000_000_000) # 350ns -> 290ns

def test_zero_value():
    # Test zero nanoseconds
    codeflash_output = format_time(0) # 731ns -> 521ns

def test_maximum_supported_value():
    # Test a very large value within reasonable range
    codeflash_output = format_time(999_999_999_999_999_999) # 2.05μs -> 1.71μs

def test_formatting_precision_boundaries():
    # Test boundaries for formatting (e.g., when value crosses 10 or 100)
    codeflash_output = format_time(9_999) # 571ns -> 421ns
    codeflash_output = format_time(99_999) # 571ns -> 421ns
    codeflash_output = format_time(999_999) # 571ns -> 421ns
    codeflash_output = format_time(9_999_999) # 571ns -> 421ns
    codeflash_output = format_time(99_999_999) # 571ns -> 421ns
    codeflash_output = format_time(999_999_999) # 571ns -> 421ns
    codeflash_output = format_time(9_999_999_999) # 571ns -> 421ns
    codeflash_output = format_time(99_999_999_999) # 571ns -> 421ns
    codeflash_output = format_time(999_999_999_999) # 571ns -> 421ns

# 3. Large Scale Test Cases

def test_many_ns_values_bulk():
    # Test a large number of values in the nanoseconds range
    for ns in range(0, 1000):
        codeflash_output = format_time(ns) # 270ns -> 220ns

def test_many_microsecond_values_bulk():
    # Test a range of values in the microseconds range
    for ns in range(1000, 998000, 997):  # Step chosen to keep <1000 iterations
        value = ns / 1_000
        if value >= 100:
            expected = f"{int(value)}μs"
        elif value >= 10:
            expected = f"{value:.1f}μs"
        else:
            expected = f"{value:.2f}μs"
        codeflash_output = format_time(ns) # 450ns -> 310ns

def test_many_millisecond_values_bulk():
    # Test a range of values in the milliseconds range
    for ns in range(1000000, 998000000, 997000):  # Step chosen to keep <1000 iterations
        value = ns / 1_000_000
        if value >= 100:
            expected = f"{int(value)}ms"
        elif value >= 10:
            expected = f"{value:.1f}ms"
        else:
            expected = f"{value:.2f}ms"
        codeflash_output = format_time(ns) # 420ns -> 280ns

def test_many_second_values_bulk():
    # Test a range of values in the seconds range
    for ns in range(1000000000, 998000000000, 997000000):  # Step chosen to keep <1000 iterations
        value = ns / 1_000_000_000
        if value >= 100:
            expected = f"{int(value)}s"
        elif value >= 10:
            expected = f"{value:.1f}s"
        else:
            expected = f"{value:.2f}s"
        codeflash_output = format_time(ns) # 441ns -> 330ns

def test_performance_large_list():
    # Test performance and correctness on a list of 1000 increasing values
    ns_values = [i * 1_000_000 for i in range(1000)]  # 0ms to 999ms
    expected = []
    for i in range(1000):
        ns = i * 1_000_000
        if ns < 1_000:
            expected.append(f"{ns}ns")
        elif ns < 1_000_000:
            value = ns / 1_000
            if value >= 100:
                expected.append(f"{int(value)}μs")
            elif value >= 10:
                expected.append(f"{value:.1f}μs")
            else:
                expected.append(f"{value:.2f}μs")
        elif ns < 1_000_000_000:
            value = ns / 1_000_000
            if value >= 100:
                expected.append(f"{int(value)}ms")
            elif value >= 10:
                expected.append(f"{value:.1f}ms")
            else:
                expected.append(f"{value:.2f}ms")
        else:
            value = ns / 1_000_000_000
            if value >= 100:
                expected.append(f"{int(value)}s")
            elif value >= 10:
                expected.append(f"{value:.1f}s")
            else:
                expected.append(f"{value:.2f}s")
    actual = [format_time(ns) for ns in ns_values]
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

from codeflash.code_utils.time_utils import format_time

def test_format_time():
    format_time(10000000)

def test_format_time_2():
    format_time(100000)

def test_format_time_3():
    format_time(0)

def test_format_time_4():
    format_time(1000000000)

To test or edit this optimization locally git merge codeflash/optimize-pr301-2025-06-06T22.07.22

Click to see suggested changes
Suggested change
# Define conversion factors and units
conversions = [(1_000_000_000, "s"), (1_000_000, "ms"), (1_000, "μs"), (1, "ns")]
# Handle nanoseconds case directly (no decimal formatting needed)
if nanoseconds < 1_000:
return f"{nanoseconds}ns"
if nanoseconds < 1_000_000:
microseconds_int = nanoseconds // 1_000
if microseconds_int >= 100:
return f"{microseconds_int}μs"
microseconds = nanoseconds / 1_000
# Format with precision: 3 significant digits
if microseconds >= 100:
return f"{microseconds:.0f}μs"
if microseconds >= 10:
return f"{microseconds:.1f}μs"
return f"{microseconds:.2f}μs"
if nanoseconds < 1_000_000_000:
milliseconds_int = nanoseconds // 1_000_000
if milliseconds_int >= 100:
return f"{milliseconds_int}ms"
milliseconds = nanoseconds / 1_000_000
if milliseconds >= 100:
return f"{milliseconds:.0f}ms"
if milliseconds >= 10:
return f"{milliseconds:.1f}ms"
return f"{milliseconds:.2f}ms"
seconds_int = nanoseconds // 1_000_000_000
if seconds_int >= 100:
return f"{seconds_int}s"
seconds = nanoseconds / 1_000_000_000
if seconds >= 100:
return f"{seconds:.0f}s"
if seconds >= 10:
return f"{seconds:.1f}s"
return f"{seconds:.2f}s"
# Find appropriate unit
for divisor, unit in conversions:
if nanoseconds >= divisor:
value = nanoseconds / divisor
int_value = nanoseconds // divisor
# Use integer formatting for values >= 100
if int_value >= 100:
formatted_value = str(int_value)
# Format with precision for 3 significant digits
elif value >= 100:
formatted_value = f"{value:.0f}"
elif value >= 10:
formatted_value = f"{value:.1f}"
else:
formatted_value = f"{value:.2f}"
return f"{formatted_value}{unit}"
# This should never be reached, but included for completeness
return f"{nanoseconds}ns"
# Fast path for small values
if nanoseconds < 1_000:
return f"{nanoseconds}ns"
# Inline conversion check for speed: no for loop
if nanoseconds >= 1_000_000_000:
divisor, unit = 1_000_000_000, "s"
elif nanoseconds >= 1_000_000:
divisor, unit = 1_000_000, "ms"
elif nanoseconds >= 1_000:
divisor, unit = 1_000, "μs"
else:
# Should not happen, fallback to ns
return f"{nanoseconds}ns"
value = nanoseconds / divisor
int_value = nanoseconds // divisor
# Use integer formatting for values >= 100
if int_value >= 100:
return str(int_value) + unit
# Format with precision for 3 significant digits
if value >= 100:
return f"{value:.0f}{unit}"
if value >= 10:
return f"{value:.1f}{unit}"
return f"{value:.2f}{unit}"
_CONVERSION_UNITS = ((1_000_000_000, "s"), (1_000_000, "ms"), (1_000, "μs"))

27 changes: 16 additions & 11 deletions codeflash/context/unused_definition_remover.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
import ast
from collections import defaultdict
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from pathlib import Path
from typing import TYPE_CHECKING, Optional

import libcst as cst

from codeflash.cli_cmds.console import logger
from codeflash.code_utils.code_replacer import replace_function_definitions_in_module
from codeflash.models.models import CodeOptimizationContext, FunctionSource

if TYPE_CHECKING:
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
from codeflash.models.models import CodeOptimizationContext, FunctionSource


@dataclass
Expand Down Expand Up @@ -493,11 +499,12 @@ def print_definitions(definitions: dict[str, UsageInfo]) -> None:


def revert_unused_helper_functions(
project_root, unused_helpers: list[FunctionSource], original_helper_code: dict[Path, str]
project_root: Path, unused_helpers: list[FunctionSource], original_helper_code: dict[Path, str]
) -> None:
"""Revert unused helper functions back to their original definitions.

Args:
project_root: project_root
unused_helpers: List of unused helper functions to revert
original_helper_code: Dictionary mapping file paths to their original code

Expand All @@ -516,9 +523,6 @@ def revert_unused_helper_functions(
for file_path, helpers_in_file in unused_helpers_by_file.items():
if file_path in original_helper_code:
try:
# Read current file content
current_code = file_path.read_text(encoding="utf8")

# Get original code for this file
original_code = original_helper_code[file_path]

Expand Down Expand Up @@ -557,7 +561,6 @@ def _analyze_imports_in_optimized_code(
# Precompute a two-level dict: module_name -> func_name -> [helpers]
helpers_by_file_and_func = defaultdict(dict)
helpers_by_file = defaultdict(list) # preserved for "import module"
helpers_append = helpers_by_file_and_func.setdefault
for helper in code_context.helper_functions:
jedi_type = helper.jedi_definition.type
if jedi_type != "class":
Expand Down Expand Up @@ -606,11 +609,12 @@ def _analyze_imports_in_optimized_code(


def detect_unused_helper_functions(
function_to_optimize, code_context: CodeOptimizationContext, optimized_code: str
function_to_optimize: FunctionToOptimize, code_context: CodeOptimizationContext, optimized_code: str
) -> list[FunctionSource]:
"""Detect helper functions that are no longer called by the optimized entrypoint function.

Args:
function_to_optimize: The function to optimize
code_context: The code optimization context containing helper functions
optimized_code: The optimized code to analyze

Expand Down Expand Up @@ -702,8 +706,9 @@ def detect_unused_helper_functions(
logger.debug(f"Helper function {helper_qualified_name} is still called in optimized code")
logger.debug(f" Called via: {possible_call_names.intersection(called_function_names)}")

return unused_helpers
ret_val = unused_helpers

except Exception as e:
logger.debug(f"Error detecting unused helper functions: {e}")
return []
ret_val = []
return ret_val
Loading