Thanks to visit codestin.com
Credit goes to github.com

Skip to content

⚑️ Speed up function _init_subplot_domain by 9% #122

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

πŸ“„ 9% (0.09x) speedup for _init_subplot_domain in plotly/_subplots.py

⏱️ Runtime : 55.6 microseconds β†’ 51.2 microseconds (best of 729 runs)

πŸ“ Explanation and details

Here is a fully optimized version of your function, minimizing allocation and optimizing tuple/list conversion while preserving exactly the same return value, API, and doc comments.

Key optimizations.

  • The only non-literal work is creating tuple(x_domain) and tuple(y_domain), which are mandatory if you want to ensure tuple types regardless of input (so these remain).
  • layout_keys=() is a static empty tuple (no cost).
  • No need to touch the return tuple construction.
  • Reduce dictionary creation overhead with local variable (micro-optimization).
  • Avoid multi-line indents for the namedtuple -- direct single-line is slightly more efficient.

Notes.

  • This is about as fast as this construction can be, given the required tuple creation and immutable namedtuple usage.
  • Any further "optimization" would be microseconds at best, limited by the need to wrap the input iterables as tuples and the requirements for the namedtuple construction.

βœ… Correctness verification report:

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

# imports
import pytest  # used for our unit tests
from plotly._subplots import _init_subplot_domain

# function to test
# Constants
# ---------
# Subplot types that are each individually positioned with a domain
#
# Each of these subplot types has a `domain` property with `x`/`y`
# properties.
# Note that this set does not contain `xaxis`/`yaxis` because these behave a
# little differently.

SubplotRef = collections.namedtuple(
    "SubplotRef", ("subplot_type", "layout_keys", "trace_kwargs")
)
from plotly._subplots import _init_subplot_domain

# unit tests

# 1. Basic Test Cases

def test_basic_valid_domains():
    # Test with typical domains
    x = [0.0, 1.0]
    y = [0.0, 1.0]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_basic_non_unit_domains():
    # Test with domains not spanning [0, 1]
    x = [0.2, 0.8]
    y = [0.3, 0.7]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_basic_integer_domains():
    # Test with integer values
    x = [1, 2]
    y = [3, 4]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_basic_tuple_input():
    # Accept tuples as input
    x = (0.1, 0.9)
    y = (0.2, 0.8)
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_basic_mixed_types():
    # Accept mixed list/tuple input
    x = [0.3, 0.7]
    y = (0.4, 0.6)
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

# 2. Edge Test Cases

def test_edge_empty_domains():
    # Edge: Empty domains
    x = []
    y = []
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_single_element_domains():
    # Edge: Domains with a single value
    x = [0.5]
    y = [0.7]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_negative_values():
    # Edge: Negative values in domains
    x = [-1.0, 0.0]
    y = [-2.0, -1.0]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_large_values():
    # Edge: Very large values in domains
    x = [1e10, 1e12]
    y = [1e15, 1e16]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_non_numeric_values():
    # Edge: Non-numeric values (should be accepted as is)
    x = ['a', 'b']
    y = ['c', 'd']
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_nested_domains():
    # Edge: Nested lists/tuples
    x = [[0, 1], [2, 3]]
    y = [(4, 5), (6, 7)]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_edge_mutable_input_immutability():
    # Edge: Input lists should not be mutated
    x = [0.1, 0.2]
    y = [0.3, 0.4]
    codeflash_output = _init_subplot_domain(x, y); _ = codeflash_output

def test_edge_different_lengths():
    # Edge: Domains of different lengths
    x = [0.1, 0.2, 0.3]
    y = [0.4]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

# 3. Large Scale Test Cases

def test_large_scale_domains_1000_elements():
    # Large scale: domains with 1000 elements
    x = list(range(1000))
    y = list(range(1000, 2000))
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_large_scale_domains_large_numbers():
    # Large scale: domains with large numbers and negative values
    x = list(range(-500, 500))
    y = list(range(500, 1500))
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_large_scale_domains_strings():
    # Large scale: domains with string values
    x = [f"x{i}" for i in range(1000)]
    y = [f"y{i}" for i in range(1000)]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_large_scale_domains_nested():
    # Large scale: domains with nested tuples/lists
    x = [(i, i+1) for i in range(500)]
    y = [[i, i+1] for i in range(500)]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]

def test_large_scale_domains_mixed_types():
    # Large scale: domains with mixed types
    x = [i if i % 2 == 0 else str(i) for i in range(1000)]
    y = [float(i) for i in range(1000)]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    subplot_ref = result[0]
    expected_x = tuple(i if i % 2 == 0 else str(i) for i in range(1000))
    expected_y = tuple(float(i) for i in range(1000))
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import collections

# imports
import pytest  # used for our unit tests
from plotly._subplots import _init_subplot_domain

# function to test
# Constants
# ---------
# Subplot types that are each individually positioned with a domain
#
# Each of these subplot types has a `domain` property with `x`/`y`
# properties.
# Note that this set does not contain `xaxis`/`yaxis` because these behave a
# little differently.

SubplotRef = collections.namedtuple(
    "SubplotRef", ("subplot_type", "layout_keys", "trace_kwargs")
)
from plotly._subplots import _init_subplot_domain

# unit tests

# 1. BASIC TEST CASES

def test_basic_valid_domains():
    # Test with standard domain values [0, 1]
    codeflash_output = _init_subplot_domain([0, 1], [0, 1]); result = codeflash_output
    ref = result[0]

def test_basic_tuple_input():
    # Test with tuples as input
    codeflash_output = _init_subplot_domain((0.2, 0.8), (0.3, 0.7)); result = codeflash_output
    ref = result[0]

def test_basic_mixed_types():
    # Test with list for x and tuple for y
    codeflash_output = _init_subplot_domain([0.1, 0.9], (0.4, 0.6)); result = codeflash_output
    ref = result[0]

def test_basic_negative_and_positive():
    # Test with negative and positive values
    codeflash_output = _init_subplot_domain([-0.5, 0.5], [-1, 1]); result = codeflash_output
    ref = result[0]

def test_basic_float_precision():
    # Test with float values with high precision
    codeflash_output = _init_subplot_domain([0.123456789, 0.987654321], [0.111111111, 0.999999999]); result = codeflash_output
    ref = result[0]

# 2. EDGE TEST CASES

def test_edge_empty_lists():
    # Test with empty lists
    codeflash_output = _init_subplot_domain([], []); result = codeflash_output
    ref = result[0]

def test_edge_single_element_lists():
    # Test with single element lists
    codeflash_output = _init_subplot_domain([0.5], [0.5]); result = codeflash_output
    ref = result[0]

def test_edge_large_numbers():
    # Test with very large numbers
    codeflash_output = _init_subplot_domain([1e10, 2e10], [3e10, 4e10]); result = codeflash_output
    ref = result[0]

def test_edge_small_numbers():
    # Test with very small numbers
    codeflash_output = _init_subplot_domain([1e-10, 2e-10], [3e-10, 4e-10]); result = codeflash_output
    ref = result[0]

def test_edge_non_numeric_types():
    # Test with non-numeric types (should still convert to tuple)
    codeflash_output = _init_subplot_domain(['a', 'b'], ['c', 'd']); result = codeflash_output
    ref = result[0]

def test_edge_mutable_input_immutability():
    # Test that input lists are not mutated (immutability)
    x = [0.1, 0.2]
    y = [0.3, 0.4]
    codeflash_output = _init_subplot_domain(x, y); _ = codeflash_output

def test_edge_nested_lists():
    # Test with nested lists (should be converted to tuple, not flattened)
    codeflash_output = _init_subplot_domain([[0, 1]], [[2, 3]]); result = codeflash_output
    ref = result[0]

def test_edge_longer_than_two_elements():
    # Test with more than two elements in domain
    codeflash_output = _init_subplot_domain([0, 0.5, 1], [0, 0.5, 1]); result = codeflash_output
    ref = result[0]

def test_edge_none_values():
    # Test with None values in domain
    codeflash_output = _init_subplot_domain([None, 1], [0, None]); result = codeflash_output
    ref = result[0]

def test_edge_mixed_types_in_list():
    # Test with mixed types in domain lists
    codeflash_output = _init_subplot_domain([0, 'a', None], [1, 2.5, False]); result = codeflash_output
    ref = result[0]

# 3. LARGE SCALE TEST CASES

def test_large_scale_100_elements():
    # Test with 100 elements in each domain
    x = list(range(100))
    y = list(range(100, 200))
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    ref = result[0]

def test_large_scale_max_elements():
    # Test with 999 elements in each domain (near the 1000 element limit)
    x = list(range(999))
    y = list(range(999, 1998))
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    ref = result[0]

def test_large_scale_performance():
    # Test that function completes in reasonable time for large input
    import time
    x = list(range(999))
    y = list(range(999))
    start = time.time()
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    duration = time.time() - start
    ref = result[0]

def test_large_scale_large_strings():
    # Test with large string values in the domain
    x = ['x' * 100 for _ in range(500)]
    y = ['y' * 100 for _ in range(500)]
    codeflash_output = _init_subplot_domain(x, y); result = codeflash_output
    ref = result[0]
# 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-_init_subplot_domain-mb2h5mel and push.

Codeflash

Here is a fully optimized version of your function, minimizing allocation and optimizing tuple/list conversion while preserving exactly the same return value, API, and doc comments.

### Key optimizations.

- The only non-literal work is creating `tuple(x_domain)` and `tuple(y_domain)`, which are mandatory if you want to ensure tuple types regardless of input (so these remain).
- `layout_keys=()` is a static empty tuple (no cost).
- No need to touch the return tuple construction.
- Reduce dictionary creation overhead with local variable (micro-optimization).
- Avoid multi-line indents for the namedtuple -- direct single-line is slightly more efficient.



### Notes.
- This is about as fast as this construction can be, given the required tuple creation and immutable namedtuple usage.
- Any further "optimization" would be microseconds at best, limited by the need to wrap the input iterables as tuples and the requirements for the namedtuple construction.
@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 16:59
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