Skip to content

⚡️ Speed up function _legend_annotation by 99% #115

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 1 commit into
base: main
Choose a base branch
from

Conversation

codeflash-ai[bot]
Copy link

@codeflash-ai codeflash-ai bot commented May 24, 2025

📄 99% (0.99x) speedup for _legend_annotation in plotly/figure_factory/_facet_grid.py

⏱️ Runtime : 602 microseconds 303 microseconds (best of 454 runs)

📝 Explanation and details

Here is a faster version of your Python program.
Optimizations applied:

  • Move the static sub-dictionaries (e.g., font) to a module-level constant so they're constructed only once.
  • Use f-strings for more efficient string formatting.
  • Use the dict.copy() method to avoid repeated construction of the dictionary, and only change the color name string.
  • This reduces allocations and time spent re-creating the same structure each call.

Optimized code:

Behavior is preserved; performance is improved by reducing repeated work.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 1061 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests Details
import pytest  # used for our unit tests
from plotly.figure_factory._facet_grid import _legend_annotation

# function to test
LEGEND_ANNOT_X = 1.05
from plotly.figure_factory._facet_grid import _legend_annotation

# unit tests

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

def test_basic_string():
    # Test with a typical string
    codeflash_output = _legend_annotation("red"); result = codeflash_output
    # Check all expected keys exist
    expected_keys = {
        "textangle", "xanchor", "yanchor", "x", "y", "showarrow",
        "xref", "yref", "text", "font"
    }

def test_basic_string_with_spaces():
    # Test with a string containing spaces
    codeflash_output = _legend_annotation("my color"); result = codeflash_output

def test_basic_string_with_special_chars():
    # Test with a string containing special characters
    codeflash_output = _legend_annotation("blue-green_#1!"); result = codeflash_output

def test_basic_numeric_string():
    # Test with a string that looks like a number
    codeflash_output = _legend_annotation("12345"); result = codeflash_output

def test_basic_empty_string():
    # Test with an empty string
    codeflash_output = _legend_annotation(""); result = codeflash_output

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

def test_edge_none():
    # Test with None as input
    codeflash_output = _legend_annotation(None); result = codeflash_output

def test_edge_boolean_true():
    # Test with boolean True
    codeflash_output = _legend_annotation(True); result = codeflash_output

def test_edge_boolean_false():
    # Test with boolean False
    codeflash_output = _legend_annotation(False); result = codeflash_output

def test_edge_integer():
    # Test with an integer input
    codeflash_output = _legend_annotation(42); result = codeflash_output

def test_edge_float():
    # Test with a float input
    codeflash_output = _legend_annotation(3.1415); result = codeflash_output

def test_edge_list():
    # Test with a list input
    codeflash_output = _legend_annotation(['a', 'b']); result = codeflash_output

def test_edge_dict():
    # Test with a dict input
    codeflash_output = _legend_annotation({'a': 1}); result = codeflash_output

def test_edge_object():
    # Test with a custom object
    class Dummy:
        def __str__(self):
            return "DummyObject"
    dummy = Dummy()
    codeflash_output = _legend_annotation(dummy); result = codeflash_output

def test_edge_long_string():
    # Test with a very long string
    long_str = "x" * 500
    codeflash_output = _legend_annotation(long_str); result = codeflash_output

def test_edge_unicode_string():
    # Test with unicode characters
    codeflash_output = _legend_annotation("café-🚀"); result = codeflash_output

def test_edge_tuple():
    # Test with a tuple input
    codeflash_output = _legend_annotation((1, 2)); result = codeflash_output

def test_edge_bytes():
    # Test with bytes input
    codeflash_output = _legend_annotation(b"bytes"); result = codeflash_output

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

def test_large_scale_many_calls():
    # Test calling the function with many different inputs to check for memory leaks or slowdowns
    for i in range(1000):
        value = f"color_{i}"
        codeflash_output = _legend_annotation(value); result = codeflash_output

def test_large_scale_long_input():
    # Test with a very large input string (999 characters)
    long_input = "a" * 999
    codeflash_output = _legend_annotation(long_input); result = codeflash_output

def test_large_scale_large_object_repr():
    # Test with an object whose __str__ returns a large string
    class LargeStr:
        def __str__(self):
            return "L" * 999
    obj = LargeStr()
    codeflash_output = _legend_annotation(obj); result = codeflash_output

def test_large_scale_varied_types():
    # Test with a variety of types in a single run
    inputs = [
        "simple",
        123,
        45.67,
        None,
        [1, 2, 3],
        {"k": "v"},
        (9, 8, 7),
        True,
        b"bytes",
        "unicode-✓",
        "",
        " " * 100,
    ]
    for val in inputs:
        codeflash_output = _legend_annotation(val); result = codeflash_output
# 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 plotly.figure_factory._facet_grid import _legend_annotation

# function to test
LEGEND_ANNOT_X = 1.05
from plotly.figure_factory._facet_grid import _legend_annotation

# unit tests

# --- 1. Basic Test Cases ---

def test_basic_string_input():
    # Test with a normal string input
    color_name = "red"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_basic_integer_input():
    # Test with an integer input
    color_name = 42
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_basic_float_input():
    # Test with a float input
    color_name = 3.14
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_basic_bool_input():
    # Test with a boolean input
    color_name = True
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_basic_none_input():
    # Test with None as input
    color_name = None
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

# --- 2. Edge Test Cases ---

def test_empty_string_input():
    # Test with empty string
    color_name = ""
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_long_string_input():
    # Test with a very long string
    color_name = "x" * 500
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_special_characters_string():
    # Test with a string containing special characters
    color_name = "!@#$%^&*()_+-=[]{}|;':,.<>/?`~"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_unicode_string():
    # Test with unicode input
    color_name = "蓝色"  # Chinese for blue
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_list_input():
    # Test with a list input
    color_name = [1, 2, 3]
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_dict_input():
    # Test with a dict input
    color_name = {"a": 1}
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_tuple_input():
    # Test with a tuple input
    color_name = (1, "b")
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_object_input():
    # Test with a custom object input
    class Dummy:
        def __repr__(self):
            return "DummyObject"
    color_name = Dummy()
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_input_with_newlines_and_tabs():
    # Test with string containing newlines and tabs
    color_name = "line1\nline2\tend"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_input_with_formatting_braces():
    # Test with string containing curly braces
    color_name = "foo{bar}"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_input_with_percent_sign():
    # Test with string containing percent sign
    color_name = "100%"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_input_with_escaped_characters():
    # Test with string containing escaped characters
    color_name = "a\\b\\c"
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

# --- 3. Large Scale Test Cases ---

def test_large_integer_input():
    # Test with a very large integer input
    color_name = 10 ** 100  # 101-digit integer
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_large_list_input():
    # Test with a list of 1000 elements
    color_name = list(range(1000))
    codeflash_output = _legend_annotation(color_name); result = codeflash_output
    # Check that the text starts and ends as expected
    text = result["text"]

def test_large_string_input():
    # Test with a string of 1000 characters
    color_name = "y" * 1000
    codeflash_output = _legend_annotation(color_name); result = codeflash_output

def test_large_dict_input():
    # Test with a dict of 1000 elements
    color_name = {str(i): i for i in range(1000)}
    codeflash_output = _legend_annotation(color_name); result = codeflash_output
    text = result["text"]

def test_performance_large_inputs():
    # Test that function does not raise or hang with large input
    import time
    color_name = "z" * 999
    start = time.time()
    codeflash_output = _legend_annotation(color_name); result = codeflash_output
    duration = time.time() - start

# --- 4. Determinism Test ---

def test_determinism():
    # The function should be deterministic for the same input
    color_name = "repeatable"
    codeflash_output = _legend_annotation(color_name); result1 = codeflash_output
    codeflash_output = _legend_annotation(color_name); result2 = codeflash_output

# --- 5. Type Robustness ---

@pytest.mark.parametrize("input_value,expected_text", [
    (None, "factor(None)"),
    (False, "factor(False)"),
    (0, "factor(0)"),
    ([], "factor([])"),
    ({}, "factor({})"),
    ((), "factor(())"),
])
def test_various_types(input_value, expected_text):
    # Test with various edge-case types
    codeflash_output = _legend_annotation(input_value); result = codeflash_output
# 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-_legend_annotation-mb2eaj3g and push.

Codeflash

Here is a faster version of your Python program.  
**Optimizations applied:**
- Move the static sub-dictionaries (e.g., `font`) to a module-level constant so they're constructed only once.
- Use f-strings for more efficient string formatting.
- Use the `dict.copy()` method to avoid repeated construction of the dictionary, and only change the color name string.
- This reduces allocations and time spent re-creating the same structure each call.

**Optimized code:**

**Behavior is preserved; performance is improved by reducing repeated work.**
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label May 24, 2025
@codeflash-ai codeflash-ai bot requested a review from misrasaurabh1 May 24, 2025 15:39
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants