Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

⚡️ Speed up function convert_rgba_array by 65% #5244

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

Conversation

@misrasaurabh1
Copy link

@misrasaurabh1 misrasaurabh1 commented Jun 20, 2025

📄 65% (0.65x) speedup for convert_rgba_array in plotly/matplotlylib/mpltools.py

⏱️ Runtime : 5.66 milliseconds 3.44 milliseconds (best of 166 runs)

📝 Explanation and details

Here is a faster, more memory-efficient rewrite. This version avoids unnecessary list creation, uses list comprehensions for performance, and eliminates intermediate variables. The output is unchanged.

Changes:

  • Eliminated clean_color_list.
  • Used a single efficient list comprehension without intermediate dicts.
  • Switched .format to f-strings (faster in modern Python).
  • Preserved function signature and return value.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 46 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.matplotlylib.mpltools import convert_rgba_array
# unit tests
# 1. BASIC TEST CASES
def test_single_color_middle_values():
 # Test with a single color with mid-range values
 input_colors = [(0.5, 0.5, 0.5, 0.5)]
 expected = "rgba(127,127,127,0.5)"
 codeflash_output = convert_rgba_array(input_colors)
def test_single_color_all_zeros():
 # Test with a single color, all zeros (black, fully transparent)
 input_colors = [(0.0, 0.0, 0.0, 0.0)]
 expected = "rgba(0,0,0,0.0)"
 codeflash_output = convert_rgba_array(input_colors)
def test_single_color_all_ones():
 # Test with a single color, all ones (white, fully opaque)
 input_colors = [(1.0, 1.0, 1.0, 1.0)]
 expected = "rgba(255,255,255,1.0)"
 codeflash_output = convert_rgba_array(input_colors)
def test_multiple_colors_basic():
 # Test with two distinct colors
 input_colors = [(1.0, 0.0, 0.0, 1.0), (0.0, 1.0, 0.0, 0.5)]
 expected = ["rgba(255,0,0,1.0)", "rgba(0,255,0,0.5)"]
 codeflash_output = convert_rgba_array(input_colors)
def test_multiple_colors_varied():
 # Test with three colors, varying alpha and RGB
 input_colors = [
 (0.2, 0.4, 0.6, 0.8),
 (0.9, 0.1, 0.3, 0.2),
 (0.0, 0.0, 1.0, 1.0)
 ]
 expected = [
 "rgba(51,102,153,0.8)",
 "rgba(229,25,76,0.2)",
 "rgba(0,0,255,1.0)"
 ]
 codeflash_output = convert_rgba_array(input_colors)
# 2. EDGE TEST CASES
def test_empty_list():
 # Test with an empty list (should return an empty list)
 input_colors = []
 expected = []
 codeflash_output = convert_rgba_array(input_colors)
def test_minimal_alpha():
 # Test with alpha = 0.0 (fully transparent)
 input_colors = [(0.1, 0.2, 0.3, 0.0)]
 expected = "rgba(25,51,76,0.0)"
 codeflash_output = convert_rgba_array(input_colors)
def test_maximal_alpha():
 # Test with alpha = 1.0 (fully opaque)
 input_colors = [(0.1, 0.2, 0.3, 1.0)]
 expected = "rgba(25,51,76,1.0)"
 codeflash_output = convert_rgba_array(input_colors)
def test_floats_near_zero():
 # Test with values very close to zero
 input_colors = [(0.0001, 0.0002, 0.0003, 0.0004)]
 expected = "rgba(0,0,0,0.0004)"
 codeflash_output = convert_rgba_array(input_colors)
def test_floats_near_one():
 # Test with values very close to one
 input_colors = [(0.9999, 0.9998, 0.9997, 0.9996)]
 expected = "rgba(254,254,254,0.9996)"
 codeflash_output = convert_rgba_array(input_colors)
def test_rounding_down():
 # Test that values just below .5 round down
 input_colors = [(0.499, 0.499, 0.499, 0.5)]
 expected = "rgba(127,127,127,0.5)"
 codeflash_output = convert_rgba_array(input_colors)
def test_rounding_up():
 # Test that values just above .5 round up
 input_colors = [(0.501, 0.501, 0.501, 0.5)]
 expected = "rgba(127,127,127,0.5)"
 codeflash_output = convert_rgba_array(input_colors)
def test_alpha_precision():
 # Test that alpha is preserved as a float, not rounded
 input_colors = [(0.1, 0.2, 0.3, 0.123456)]
 expected = "rgba(25,51,76,0.123456)"
 codeflash_output = convert_rgba_array(input_colors)
def test_input_tuple_length():
 # Test with invalid input: tuple of wrong length
 input_colors = [(0.1, 0.2, 0.3)] # missing alpha
 with pytest.raises(IndexError):
 convert_rgba_array(input_colors)
def test_input_value_out_of_range():
 # Test with values outside [0, 1] -- should not clamp, just multiply
 input_colors = [(-0.1, 1.2, 0.5, 1.5)]
 expected = "rgba(-25,306,127,1.5)"
 codeflash_output = convert_rgba_array(input_colors)
def test_input_non_float_values():
 # Test with integer input values (should work, as int * 255 is valid)
 input_colors = [(1, 0, 0, 1)]
 expected = "rgba(255,0,0,1)"
 codeflash_output = convert_rgba_array(input_colors)
def test_input_as_list_instead_of_tuple():
 # Test with color as a list instead of a tuple
 input_colors = [[0.1, 0.2, 0.3, 0.4]]
 expected = "rgba(25,51,76,0.4)"
 codeflash_output = convert_rgba_array(input_colors)
def test_large_number_of_colors():
 # Test with 1000 colors, all unique
 input_colors = [(i/1000, (1000-i)/1000, (i%256)/255, (i%100)/100) for i in range(1000)]
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_all_same_color():
 # Test with 1000 identical colors
 input_colors = [(0.1, 0.2, 0.3, 0.4)] * 1000
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_all_different_alpha():
 # Test with 1000 colors, all different alpha
 input_colors = [(0.5, 0.5, 0.5, i/1000) for i in range(1000)]
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_extreme_values():
 # Test with 1000 colors, alternating extreme values
 input_colors = []
 for i in range(1000):
 if i % 2 == 0:
 input_colors.append((0.0, 0.0, 0.0, 0.0))
 else:
 input_colors.append((1.0, 1.0, 1.0, 1.0))
 codeflash_output = convert_rgba_array(input_colors); 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.matplotlylib.mpltools import convert_rgba_array
# unit tests
# ----------- Basic Test Cases -----------
def test_single_color_basic():
 # Test with a single RGBA color
 input_color = [(1.0, 0.0, 0.0, 0.5)] # Red, half transparent
 expected = "rgba(255,0,0,0.5)"
 codeflash_output = convert_rgba_array(input_color)
def test_multiple_colors_basic():
 # Test with multiple RGBA colors
 input_colors = [
 (1.0, 0.0, 0.0, 1.0), # Red, opaque
 (0.0, 1.0, 0.0, 0.5), # Green, half transparent
 (0.0, 0.0, 1.0, 0.0) # Blue, fully transparent
 ]
 expected = [
 "rgba(255,0,0,1.0)",
 "rgba(0,255,0,0.5)",
 "rgba(0,0,255,0.0)"
 ]
 codeflash_output = convert_rgba_array(input_colors)
def test_single_color_full_black():
 # Test with a single black color, fully opaque
 input_color = [(0.0, 0.0, 0.0, 1.0)]
 expected = "rgba(0,0,0,1.0)"
 codeflash_output = convert_rgba_array(input_color)
def test_single_color_full_white():
 # Test with a single white color, fully opaque
 input_color = [(1.0, 1.0, 1.0, 1.0)]
 expected = "rgba(255,255,255,1.0)"
 codeflash_output = convert_rgba_array(input_color)
def test_single_color_no_alpha():
 # Test with a single color, fully transparent
 input_color = [(0.5, 0.5, 0.5, 0.0)]
 expected = "rgba(127,127,127,0.0)"
 codeflash_output = convert_rgba_array(input_color)
def test_alpha_precision():
 # Test with an alpha value with more decimal places
 input_color = [(0.2, 0.4, 0.6, 0.333333)]
 expected = "rgba(51,102,153,0.333333)"
 codeflash_output = convert_rgba_array(input_color)
def test_multiple_colors_varied_alpha():
 # Test with multiple colors and varied alpha values
 input_colors = [
 (0.1, 0.2, 0.3, 0.0),
 (0.4, 0.5, 0.6, 0.5),
 (0.7, 0.8, 0.9, 1.0)
 ]
 expected = [
 "rgba(25,51,76,0.0)",
 "rgba(102,127,153,0.5)",
 "rgba(178,204,229,1.0)"
 ]
 codeflash_output = convert_rgba_array(input_colors)
# ----------- Edge Test Cases -----------
def test_empty_list():
 # Test with an empty list
 input_colors = []
 expected = []
 codeflash_output = convert_rgba_array(input_colors)
def test_minimal_channel_values():
 # Test with channels at their minimum (0.0)
 input_color = [(0.0, 0.0, 0.0, 0.0)]
 expected = "rgba(0,0,0,0.0)"
 codeflash_output = convert_rgba_array(input_color)
def test_maximal_channel_values():
 # Test with channels at their maximum (1.0)
 input_color = [(1.0, 1.0, 1.0, 1.0)]
 expected = "rgba(255,255,255,1.0)"
 codeflash_output = convert_rgba_array(input_color)
def test_channel_rounding_down():
 # Test rounding down for float to int conversion
 input_color = [(0.499, 0.499, 0.499, 1.0)]
 expected = "rgba(127,127,127,1.0)" # int(0.499*255) == 127
 codeflash_output = convert_rgba_array(input_color)
def test_channel_rounding_up():
 # Test rounding up for float to int conversion
 input_color = [(0.501, 0.501, 0.501, 1.0)]
 expected = "rgba(127,127,127,1.0)" # int(0.501*255) == 127
 codeflash_output = convert_rgba_array(input_color)
def test_alpha_as_int():
 # Test with alpha as an integer (should still work)
 input_color = [(0.1, 0.2, 0.3, 1)]
 expected = "rgba(25,51,76,1)"
 codeflash_output = convert_rgba_array(input_color)
def test_alpha_as_string():
 # Test with alpha as a string (should be preserved as string)
 input_color = [(0.1, 0.2, 0.3, "0.7")]
 expected = "rgba(25,51,76,0.7)"
 codeflash_output = convert_rgba_array(input_color)
def test_negative_channel_values():
 # Test with negative channel values (should convert to negative ints)
 input_color = [(-0.1, -0.2, -0.3, 0.5)]
 expected = "rgba(-25,-51,-76,0.5)"
 codeflash_output = convert_rgba_array(input_color)
def test_channel_values_above_one():
 # Test with channel values above 1.0 (should convert to >255)
 input_color = [(1.1, 1.2, 1.3, 0.5)]
 expected = "rgba(280,306,331,0.5)"
 codeflash_output = convert_rgba_array(input_color)
def test_alpha_out_of_range():
 # Test with alpha < 0 or > 1 (should be preserved as is)
 input_colors = [
 (0.5, 0.5, 0.5, -0.1),
 (0.5, 0.5, 0.5, 1.1)
 ]
 expected = [
 "rgba(127,127,127,-0.1)",
 "rgba(127,127,127,1.1)"
 ]
 codeflash_output = convert_rgba_array(input_colors)
def test_non_tuple_input():
 # Test with a list instead of tuple for color
 input_color = [[0.1, 0.2, 0.3, 0.5]]
 expected = "rgba(25,51,76,0.5)"
 codeflash_output = convert_rgba_array(input_color)
def test_input_with_less_than_four_elements():
 # Test with a color tuple with less than 4 elements (should raise error)
 input_color = [(0.1, 0.2, 0.3)]
 with pytest.raises(IndexError):
 convert_rgba_array(input_color)
def test_input_with_nested_lists():
 # Test with nested list of colors
 input_colors = [[(0.1, 0.2, 0.3, 0.5), (0.4, 0.5, 0.6, 0.7)]]
 # Should raise error because the function expects a flat list
 with pytest.raises(TypeError):
 convert_rgba_array(input_colors)
def test_input_with_none():
 # Test with None as input
 with pytest.raises(TypeError):
 convert_rgba_array(None)
# ----------- Large Scale Test Cases -----------
def test_large_list_of_colors():
 # Test with a large list of colors (1000 elements)
 input_colors = [(i/999, (999-i)/999, 0.5, 0.5) for i in range(1000)]
 # Each color should be mapped to an rgba string
 expected = [
 "rgba({},{},{},{})".format(
 int(i/999*255),
 int((999-i)/999*255),
 int(0.5*255),
 0.5
 ) for i in range(1000)
 ]
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_list_all_same_color():
 # Test with a large list of the same color
 input_colors = [(0.1, 0.2, 0.3, 0.4)] * 1000
 expected = ["rgba(25,51,76,0.4)"] * 1000
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_list_varied_alpha():
 # Test with a large list with varying alpha values
 input_colors = [(0.5, 0.5, 0.5, i/999) for i in range(1000)]
 expected = [
 "rgba(127,127,127,{})".format(i/999) for i in range(1000)
 ]
 codeflash_output = convert_rgba_array(input_colors); result = codeflash_output
def test_large_list_edge_channel_values():
 # Test with a large list with edge channel values
 input_colors = [(1.0, 0.0, 0.0, 1.0)] * 500 + [(0.0, 1.0, 0.0, 0.0)] * 500
 expected = ["rgba(255,0,0,1.0)"] * 500 + ["rgba(0,255,0,0.0)"] * 500
 codeflash_output = convert_rgba_array(input_colors); 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.

Codeflash

codeflash-ai bot and others added 2 commits May 21, 2025 07:56
Here is a faster, more memory-efficient rewrite. This version avoids unnecessary list creation, uses list comprehensions for performance, and eliminates intermediate variables. The output is unchanged.
**Changes:**
- Eliminated `clean_color_list`.
- Used a single efficient list comprehension without intermediate dicts.
- Switched `.format` to f-strings (faster in modern Python).
- Preserved function signature and return value.
Copy link
Contributor

Thanks for the PR, but this code is nowhere near any of our critical execution paths, so the time required to review and test the change is greater than the expected benefit to users.

misrasaurabh1 reacted with thumbs up emoji

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /