Skip to content

perf: Speed up method GalileoDecorator._is_method by 33% #117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

misrasaurabh1
Copy link

πŸ“„ 33% (0.33x) speedup for GalileoDecorator._is_method in src/galileo/decorator.py

⏱️ Runtime : 578 microseconds β†’ 433 microseconds (best of 156 runs)

πŸ“ Explanation and details

Here is your optimized Python program.
All comments are preserved unless the code they describe was changed.
The major bottleneck in your code is calling inspect.signature(func) twice in _is_method, which can be expensive. We will compute it once and reuse it.
Additionally, the docstrings and structure are retained.

Optimization summary:

  • Only call inspect.signature(func) once per call to _is_method rather than twice, reducing function call overhead and making your code run faster.
  • No changes to function signatures, variable names, logic, or return values.
  • All original comments preserved.
  • No extraneous code added.

βœ… Correctness verification report:

Test Status
βš™οΈ Existing Unit Tests πŸ”˜ None Found
πŸŒ€ Generated Regression Tests βœ… 31 Passed
βͺ Replay Tests πŸ”˜ None Found
πŸ”Ž Concolic Coverage Tests πŸ”˜ None Found
πŸ“Š Tests Coverage 100.0%
πŸŒ€ Generated Regression Tests Details
import inspect
from typing import Callable

# imports
import pytest  # used for our unit tests
from galileo.decorator import GalileoDecorator

# unit tests

def test_simple_function():
    # Test case for a simple function with no parameters
    def simple_function():
        pass
    codeflash_output = not GalileoDecorator._is_method(simple_function)

def test_function_with_parameters():
    # Test case for a function with parameters other than 'self' or 'cls'
    def function_with_params(a, b):
        pass
    codeflash_output = not GalileoDecorator._is_method(function_with_params)

def test_instance_method():
    # Test case for an instance method
    class ExampleClass:
        def instance_method(self):
            pass
    codeflash_output = GalileoDecorator._is_method(ExampleClass.instance_method)

def test_class_method():
    # Test case for a class method
    class ExampleClass:
        @classmethod
        def class_method(cls):
            pass
    codeflash_output = GalileoDecorator._is_method(ExampleClass.class_method)

def test_unconventional_method_names():
    # Test case for methods with unconventional parameter names
    class ExampleClass:
        def method_with_self_renamed(this):
            pass
        @classmethod
        def method_with_cls_renamed(kls):
            pass
    codeflash_output = not GalileoDecorator._is_method(ExampleClass.method_with_self_renamed)
    codeflash_output = not GalileoDecorator._is_method(ExampleClass.method_with_cls_renamed)

def test_decorated_methods():
    # Test case for decorated methods
    class ExampleClass:
        @staticmethod
        def static_method():
            pass
    codeflash_output = not GalileoDecorator._is_method(ExampleClass.static_method)

def test_function_with_defaults():
    # Test case for a function with default values
    def function_with_defaults(a, b=10):
        pass
    codeflash_output = not GalileoDecorator._is_method(function_with_defaults)

def test_function_with_varargs():
    # Test case for a function with variable arguments
    def function_with_varargs(*args, **kwargs):
        pass
    codeflash_output = not GalileoDecorator._is_method(function_with_varargs)

def test_large_signature():
    # Test case for a function with a large number of parameters
    def function_with_many_params(a, b, c, d, e, f, g, h, i, j):
        pass
    codeflash_output = not GalileoDecorator._is_method(function_with_many_params)

def test_lambda_function():
    # Test case for a lambda function
    lambda_function = lambda x: x
    codeflash_output = not GalileoDecorator._is_method(lambda_function)

def test_callable_object():
    # Test case for a callable object
    class CallableClass:
        def __call__(self):
            pass
    callable_instance = CallableClass()
    codeflash_output = GalileoDecorator._is_method(callable_instance.__call__)


def test_consistent_results():
    # Test case to ensure consistent results
    def consistent_function():
        pass
    codeflash_output = not GalileoDecorator._is_method(consistent_function)
    codeflash_output = not GalileoDecorator._is_method(consistent_function)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import inspect
from typing import Callable

# imports
import pytest  # used for our unit tests
from galileo.decorator import GalileoDecorator

# unit tests

def test_standalone_function():
    """Test with a standalone function that has no 'self' or 'cls'."""
    def standalone_function(x, y):
        return x + y

    codeflash_output = not GalileoDecorator._is_method(standalone_function)

def test_instance_method():
    """Test with an instance method containing 'self'."""
    class SampleClass:
        def instance_method(self, x):
            return x

    codeflash_output = GalileoDecorator._is_method(SampleClass.instance_method)

def test_class_method():
    """Test with a class method containing 'cls'."""
    class SampleClass:
        @classmethod
        def class_method(cls, x):
            return x

    codeflash_output = GalileoDecorator._is_method(SampleClass.class_method)

def test_method_with_default_parameters():
    """Test with methods having default parameters."""
    class SampleClass:
        def instance_method(self, x=10):
            return x

        @classmethod
        def class_method(cls, x=10):
            return x

    codeflash_output = GalileoDecorator._is_method(SampleClass.instance_method)
    codeflash_output = GalileoDecorator._is_method(SampleClass.class_method)

def test_method_with_variable_arguments():
    """Test with methods having variable arguments."""
    class SampleClass:
        def instance_method(self, *args, **kwargs):
            return args, kwargs

        @classmethod
        def class_method(cls, *args, **kwargs):
            return args, kwargs

    codeflash_output = GalileoDecorator._is_method(SampleClass.instance_method)
    codeflash_output = GalileoDecorator._is_method(SampleClass.class_method)

def test_lambda_function():
    """Test with lambda functions that have no 'self' or 'cls'."""
    lambda_function = lambda x, y: x + y
    codeflash_output = not GalileoDecorator._is_method(lambda_function)

def test_callable_object():
    """Test with callable objects."""
    class CallableClass:
        def __call__(self, x):
            return x

    callable_instance = CallableClass()
    codeflash_output = GalileoDecorator._is_method(callable_instance.__call__)

def test_large_scale_method():
    """Test with a method having a large number of parameters."""
    class SampleClass:
        def instance_method(self, self_param, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10):
            return param1

    codeflash_output = GalileoDecorator._is_method(SampleClass.instance_method)

def test_decorated_methods():
    """Test with decorated methods."""
    def decorator(func):
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper

    class SampleClass:
        @decorator
        def instance_method(self, x):
            return x

        @decorator
        @classmethod
        def class_method(cls, x):
            return x

    codeflash_output = GalileoDecorator._is_method(SampleClass.instance_method)
    codeflash_output = GalileoDecorator._is_method(SampleClass.class_method)

def test_nested_functions():
    """Test with nested functions."""
    def outer_function():
        def inner_function(x):
            return x
        return inner_function

    codeflash_output = not GalileoDecorator._is_method(outer_function())

def test_empty_callable():
    """Test with an empty callable."""
    def empty_function():
        pass

    codeflash_output = not GalileoDecorator._is_method(empty_function)

def test_non_callable_input():
    """Test with non-callable inputs."""
    non_callable = 42
    with pytest.raises(TypeError):
        GalileoDecorator._is_method(non_callable)

    non_callable = "string"
    with pytest.raises(TypeError):
        GalileoDecorator._is_method(non_callable)

    non_callable = [1, 2, 3]
    with pytest.raises(TypeError):
        GalileoDecorator._is_method(non_callable)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

from galileo.decorator import GalileoDecorator
import pytest

def test_GalileoDecorator__is_method():
    with pytest.raises(TypeError, match='__get__\\(None,\\ None\\)\\ is\\ invalid'):
        GalileoDecorator._is_method(lambda *a: )

To edit these changes git checkout codeflash/optimize-GalileoDecorator._is_method-ma3jjm09 and push.

Codeflash

Here is your optimized Python program.  
All comments are preserved unless the code they describe was changed.  
The major bottleneck in your code is calling `inspect.signature(func)` **twice** in `_is_method`, which can be expensive. We will compute it once and reuse it.  
Additionally, the docstrings and structure are retained.



**Optimization summary:**  
- Only call `inspect.signature(func)` once per call to `_is_method` rather than twice, reducing function call overhead and making your code run faster.  
- No changes to function signatures, variable names, logic, or return values.  
- All original comments preserved.  
- No extraneous code added.
@misrasaurabh1 misrasaurabh1 requested a review from a team as a code owner May 1, 2025 00:01
@misrasaurabh1 misrasaurabh1 changed the title ⚑️ Speed up method GalileoDecorator._is_method by 33% perf: Speed up method GalileoDecorator._is_method by 33% May 1, 2025
@@ -361,7 +361,9 @@ def _is_method(func: Callable) -> bool:
Returns:
bool: True if 'cls' or 'self' is in the callable's parameters, False otherwise
"""
return "self" in inspect.signature(func).parameters or "cls" in inspect.signature(func).parameters
# Only call inspect.signature(func) ONCE for improved performance
params = inspect.signature(func).parameters
Copy link

Choose a reason for hiding this comment

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

nice

Copy link
Contributor

@andriisoldatenko andriisoldatenko left a comment

Choose a reason for hiding this comment

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

LGTM, but please remove comment, it's redundunt!

misrasaurabh1 and others added 2 commits May 8, 2025 11:21
Co-authored-by: Andrii Soldatenko <andrii.soldatenko@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants