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

Skip to content

⚑️ Speed up function _init_subplot by 11% #124

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

πŸ“„ 11% (0.11x) speedup for _init_subplot in plotly/_subplots.py

⏱️ Runtime : 785 microseconds β†’ 710 microseconds (best of 110 runs)

πŸ“ Explanation and details

Here are the concrete optimizations for your code, focusing on runtime hot spots and reducing memory allocations. The main changes target the following inefficiencies identified from your profiling.

  1. String formatting inefficiencies: The hot path is full of .format() calls for generating axis and subplot labels. These are replaced by much faster f-strings.
  2. Many redundant list/dict comprehensions and allocations: Use direct dict construction where possible, and short-circuit tuple/list creation.
  3. Repeated lookup of the same casing for subplot types: Lowercasing is now only performed once.
  4. Replacing list with tuple where possible: Where results are immutable, directly create tuples.
  5. Reducing function calls in hot loops: Avoid repeated function calls by consolidating them and removing unnecessary control flow.

All original logic and function signatures are preserved, as required.

Key optimizations:

  • All instances of .format() replaced by f-strings for fast label generation.
  • Tuple/list constructs are inlined to avoid temporaries.
  • Fast path for clamping in _init_subplot.
  • Lowercasing of subplot type is done only once in _validate_coerce_subplot_type (was repeated in every usage).
  • No allocation of unnecessary intermediate lists or dicts.

This version will be notably faster, especially for the most common code paths identified in your profiling.

βœ… Correctness verification report:

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

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

# 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.


_single_subplot_types = {"scene", "geo", "polar", "ternary", "map", "mapbox"}

# For most subplot types, a trace is associated with a particular subplot
# using a trace property with a name that matches the subplot type. For
# example, a `scatter3d.scene` property set to `'scene2'` associates a
# scatter3d trace with the second `scene` subplot in the figure.
#
# There are a few subplot types that don't follow this pattern, and instead
# the trace property is just named `subplot`.  For example setting
# the `scatterpolar.subplot` property to `polar3` associates the scatterpolar
# trace with the third polar subplot in the figure
_subplot_prop_named_subplot = {"polar", "ternary", "map", "mapbox"}
from plotly._subplots import _init_subplot

# unit tests

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

def test_xy_subplot_basic():
    # Test basic xy subplot creation with no secondary y
    layout = {}
    codeflash_output = _init_subplot(layout, "xy", False, [0.1, 0.9], [0.2, 0.8]); refs = codeflash_output
    ref = refs[0]

def test_xy_subplot_with_secondary_y():
    # Test xy subplot with secondary y axis
    layout = {}
    codeflash_output = _init_subplot(layout, "xy", True, [0.0, 1.0], [0.0, 1.0]); refs = codeflash_output

@pytest.mark.parametrize("subplot_type", ["scene", "geo", "polar", "ternary", "map", "mapbox"])
def test_single_subplot_types(subplot_type):
    # Test creation of all single subplot types
    layout = {}
    codeflash_output = _init_subplot(layout, subplot_type, False, [0.3, 0.7], [0.4, 0.6]); refs = codeflash_output
    ref = refs[0]
    # Layout key should be subplot_type or subplot_type1
    key = subplot_type
    # Trace kwargs should be correct
    if subplot_type in _subplot_prop_named_subplot:
        pass
    else:
        pass

def test_domain_subplot_type():
    # Test domain subplot type (e.g. pie chart)
    layout = {}
    codeflash_output = _init_subplot(layout, "domain", False, [0.2, 0.5], [0.1, 0.4]); refs = codeflash_output
    ref = refs[0]

def test_subplot_type_case_insensitivity():
    # Should accept upper/lower case subplot types
    layout = {}
    codeflash_output = _init_subplot(layout, "SCENE", False, [0.0, 1.0], [0.0, 1.0]); refs = codeflash_output

def test_trace_type_coercion():
    # Should coerce known trace types to subplot type
    layout = {}
    codeflash_output = _init_subplot(layout, "scatter3d", False, [0.1, 0.9], [0.2, 0.8]); refs = codeflash_output
    layout2 = {}
    codeflash_output = _init_subplot(layout2, "pie", False, [0.0, 1.0], [0.0, 1.0]); refs2 = codeflash_output

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

def test_domain_clamping():
    # Test that domains are clamped to [0, 1]
    layout = {}
    codeflash_output = _init_subplot(layout, "xy", False, [-0.5, 1.5], [-1.0, 2.0]); refs = codeflash_output



def test_invalid_subplot_type_raises():
    # Should raise ValueError for unknown subplot type
    layout = {}
    with pytest.raises(ValueError):
        _init_subplot(layout, "notasubplot", False, [0, 1], [0, 1])

def test_invalid_trace_type_raises():
    # Should raise ValueError for unknown trace type
    layout = {}
    with pytest.raises(ValueError):
        _init_subplot(layout, "unknowntrace", False, [0, 1], [0, 1])

def test_domain_empty_range():
    # Should allow zero-width/height domains as long as within [0, 1]
    layout = {}
    codeflash_output = _init_subplot(layout, "xy", False, [0.5, 0.5], [0.7, 0.7]); refs = codeflash_output

def test_domain_reverse_range():
    # Should clamp reversed domains to [0.0, 1.0]
    layout = {}
    codeflash_output = _init_subplot(layout, "xy", False, [1.5, -0.5], [2.0, -1.0]); refs = codeflash_output




def test_large_scale_domain_subplot():
    # Test many domain subplots (should not update layout)
    layout = {}
    n = 100
    for i in range(n):
        codeflash_output = _init_subplot(layout, "domain", False, [i/n, (i+1)/n], [i/n, (i+1)/n]); refs = codeflash_output
        ref = refs[0]



import collections

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

# 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.

_single_subplot_types = {"scene", "geo", "polar", "ternary", "map", "mapbox"}
from plotly._subplots import _init_subplot

# ==========================
# Unit Tests for _init_subplot
# ==========================

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

def test_xy_subplot_basic():
    # Test basic xy subplot with default max_subplot_ids, no secondary_y
    layout = {}
    codeflash_output = _init_subplot(layout, 'xy', False, [0.1, 0.9], [0.2, 0.8]); refs = codeflash_output
    ref = refs[0]

def test_xy_subplot_secondary_y():
    # Test xy subplot with secondary_y True
    layout = {}
    codeflash_output = _init_subplot(layout, 'xy', True, [0, 1], [0, 1]); refs = codeflash_output
    # First ref: primary y
    ref1 = refs[0]
    # Second ref: secondary y
    ref2 = refs[1]

def test_single_subplot_scene():
    # Test single subplot type 'scene'
    layout = {}
    codeflash_output = _init_subplot(layout, 'scene', False, [0.0, 1.0], [0.0, 1.0]); refs = codeflash_output
    ref = refs[0]

def test_single_subplot_polar():
    # Test single subplot type 'polar'
    layout = {}
    codeflash_output = _init_subplot(layout, 'polar', False, [0.1, 0.5], [0.2, 0.6]); refs = codeflash_output
    ref = refs[0]

def test_domain_subplot():
    # Test 'domain' subplot type
    layout = {}
    codeflash_output = _init_subplot(layout, 'domain', False, [0.3, 0.7], [0.4, 0.9]); refs = codeflash_output
    ref = refs[0]

def test_subplot_type_case_insensitive():
    # Test that subplot_type is case-insensitive
    layout = {}
    codeflash_output = _init_subplot(layout, 'SCENE', False, [0, 1], [0, 1]); refs = codeflash_output
    ref = refs[0]

def test_subplot_type_alias_trace_type():
    # Test subplot_type as a trace type (should resolve to subplot type)
    layout = {}
    codeflash_output = _init_subplot(layout, 'scatter3d', False, [0, 1], [0, 1]); refs = codeflash_output
    ref = refs[0]

def test_subplot_type_alias_trace_type_domain():
    # Test subplot_type as a trace type that resolves to 'domain'
    layout = {}
    codeflash_output = _init_subplot(layout, 'pie', False, [0.1, 0.9], [0.2, 0.8]); refs = codeflash_output
    ref = refs[0]

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



def test_domain_clamping():
    # Test that domain values are clamped to [0, 1]
    layout = {}
    codeflash_output = _init_subplot(layout, 'xy', False, [-0.2, 1.2], [-0.5, 2.0]); refs = codeflash_output

def test_invalid_subplot_type_raises():
    # Test that invalid subplot_type raises ValueError
    layout = {}
    with pytest.raises(ValueError):
        _init_subplot(layout, 'notasubplot', False, [0, 1], [0, 1])

def test_empty_domain():
    # Test with zero-width/height domains (should not fail, but produce degenerate domains)
    layout = {}
    codeflash_output = _init_subplot(layout, 'xy', False, [0.5, 0.5], [1.0, 1.0]); refs = codeflash_output






def test_large_number_of_domain_subplots():
    # Test many domain subplots (should not affect layout)
    layout = {}
    n = 100
    for i in range(n):
        x0 = i / n
        x1 = (i+1) / n
        y0 = 0.0
        y1 = 1.0
        codeflash_output = _init_subplot(layout, 'domain', False, [x0, x1], [y0, y1]); refs = codeflash_output
        ref = refs[0]

To edit these changes git checkout codeflash/optimize-_init_subplot-mb2he6y4 and push.

Codeflash

Here are the concrete optimizations for your code, focusing on runtime hot spots and reducing memory allocations. The main changes target the following inefficiencies identified from your profiling.

1. **String formatting inefficiencies:** The hot path is full of `.format()` calls for generating axis and subplot labels. These are replaced by much faster f-strings.
2. **Many redundant list/dict comprehensions and allocations:** Use direct dict construction where possible, and short-circuit tuple/list creation.
3. **Repeated lookup of the same casing for subplot types:** Lowercasing is now only performed once.  
4. **Replacing list with tuple where possible:** Where results are immutable, directly create tuples.
5. **Reducing function calls in hot loops:** Avoid repeated function calls by consolidating them and removing unnecessary control flow.

All original logic and function signatures are preserved, as required.




**Key optimizations:**
- All instances of `.format()` replaced by f-strings for fast label generation.
- Tuple/list constructs are inlined to avoid temporaries.
- Fast path for clamping in `_init_subplot`.
- Lowercasing of subplot type is done only once in `_validate_coerce_subplot_type` (was repeated in every usage).
- No allocation of unnecessary intermediate lists or dicts.

This version will be notably faster, especially for the most common code paths identified in your profiling.
@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 17:06
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