⚡️ Speed up function get_default_table_max_columns by 86%
#604
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 86% (0.86x) speedup for
get_default_table_max_columnsinmarimo/_plugins/ui/_impl/table.py⏱️ Runtime :
781 microseconds→419 microseconds(best of250runs)📝 Explanation and details
The optimization eliminates expensive exception handling by directly accessing the thread-local context instead of going through the
get_context()function.Key Changes:
get_context()and catchingContextNotInitializedError, the optimized version directly accesses_THREAD_LOCAL_CONTEXT.runtime_contextif ctx is None)_THREAD_LOCAL_CONTEXTdirectly to avoid the function call overheadWhy This is Faster:
Exception handling in Python is significantly more expensive than simple conditional checks. The line profiler shows that in the original code, the
get_context()call consumes 80.1% of the total execution time (6.19ms out of 7.73ms), primarily because it always raises and catchesContextNotInitializedErrorwhen the context is not initialized. The optimized version performs the same null check thatget_context()does internally, but avoids the function call overhead and exception raising/handling entirely.Performance Impact:
Test Case Analysis:
The optimization performs well across all test scenarios:
This suggests the optimization is robust and provides consistent performance benefits regardless of the context state or configuration values.
✅ Correctness verification report:
⚙️ Existing Unit Tests and Runtime
_plugins/ui/_impl/test_table.py::test_default_table_max_columns🌀 Generated Regression Tests and Runtime
import pytest
from marimo._plugins.ui._impl.table import get_default_table_max_columns
--- Function to test (as per marimo/_plugins/ui/_impl/table.py) ---
For these tests, we need to define get_context, ContextNotInitializedError,
and a mock context object. Since we cannot use pytest.mock, we'll
monkeypatch in pytest using fixtures and direct assignment.
--- Begin function and dependencies ---
DEFAULT_MAX_COLUMNS = 50
class ContextNotInitializedError(Exception):
pass
class DummyContext:
def init(self, value):
self.marimo_config = {
"display": {
"default_table_max_columns": value
}
}
We'll simulate thread-local context with a global for testing
class _ThreadLocalContext:
def init(self):
self.runtime_context = None
_THREAD_LOCAL_CONTEXT = _ThreadLocalContext()
from marimo._plugins.ui._impl.table import get_default_table_max_columns
--- Basic Test Cases ---
def test_returns_default_when_context_not_initialized():
"""Should return DEFAULT_MAX_COLUMNS if context is not initialized."""
codeflash_output = get_default_table_max_columns() # 1.19μs -> 715ns (65.9% faster)
def test_returns_configured_value_when_context_initialized():
"""Should return the configured value from context if initialized."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(42)
codeflash_output = get_default_table_max_columns() # 1.28μs -> 637ns (101% faster)
def test_returns_configured_value_with_default_value():
"""Should return DEFAULT_MAX_COLUMNS if context is initialized with default value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(DEFAULT_MAX_COLUMNS)
codeflash_output = get_default_table_max_columns() # 1.23μs -> 624ns (97.4% faster)
def test_returns_configured_value_with_high_value():
"""Should return high configured value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(100)
codeflash_output = get_default_table_max_columns() # 1.29μs -> 635ns (103% faster)
--- Edge Test Cases ---
def test_returns_zero_when_configured_zero():
"""Should handle zero value correctly (edge case)."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(0)
codeflash_output = get_default_table_max_columns() # 1.24μs -> 604ns (106% faster)
def test_returns_negative_when_configured_negative():
"""Should handle negative values (edge case)."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(-10)
codeflash_output = get_default_table_max_columns() # 1.25μs -> 649ns (92.6% faster)
def test_returns_large_value():
"""Should handle very large values."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(999_999)
codeflash_output = get_default_table_max_columns() # 1.25μs -> 655ns (90.2% faster)
def test_returns_minimum_integer():
"""Should handle minimum integer value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(-2**31)
codeflash_output = get_default_table_max_columns() # 1.22μs -> 615ns (98.7% faster)
def test_returns_maximum_integer():
"""Should handle maximum integer value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(2**31-1)
codeflash_output = get_default_table_max_columns() # 1.18μs -> 644ns (83.1% faster)
def test_returns_float_value():
"""Should handle float values (even though config expects int)."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(25.5)
codeflash_output = get_default_table_max_columns() # 1.24μs -> 673ns (83.7% faster)
def test_returns_string_value():
"""Should handle string values (type robustness)."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext("100")
codeflash_output = get_default_table_max_columns() # 1.23μs -> 588ns (109% faster)
def test_returns_none_value():
"""Should handle None value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(None)
codeflash_output = get_default_table_max_columns() # 1.21μs -> 656ns (84.0% faster)
def test_returns_list_value():
"""Should handle list value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext([1,2,3])
codeflash_output = get_default_table_max_columns() # 1.19μs -> 619ns (91.9% faster)
def test_returns_dict_value():
"""Should handle dict value."""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext({"max": 10})
codeflash_output = get_default_table_max_columns() # 1.14μs -> 663ns (72.4% faster)
--- Large Scale Test Cases ---
def test_many_context_switches():
"""Test with many context switches to ensure stability."""
for i in range(100):
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(i)
codeflash_output = get_default_table_max_columns() # 35.3μs -> 19.5μs (81.4% faster)
# Reset and check default
_THREAD_LOCAL_CONTEXT.runtime_context = None
codeflash_output = get_default_table_max_columns() # 324ns -> 177ns (83.1% faster)
def test_large_value_list():
"""Test with a large list as the value."""
large_list = list(range(1000))
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(large_list)
codeflash_output = get_default_table_max_columns() # 1.23μs -> 682ns (80.2% faster)
def test_large_scale_integer_values():
"""Test with large integer values within reasonable limits."""
for i in range(950, 1000):
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(i)
codeflash_output = get_default_table_max_columns() # 18.2μs -> 10.0μs (81.8% faster)
def test_performance_under_load():
"""Test function performance with rapid context changes."""
# Not a true performance test, but checks for scalability
values = [i for i in range(1000)]
for v in values:
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(v)
codeflash_output = get_default_table_max_columns() # 343μs -> 185μs (84.9% faster)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import pytest
from marimo._plugins.ui._impl.table import get_default_table_max_columns
function to test
DEFAULT_MAX_COLUMNS = 50
class ContextNotInitializedError(Exception):
pass
class DummyContext:
def init(self, max_columns):
self.marimo_config = {
"display": {
"default_table_max_columns": max_columns
}
}
Simulate thread-local context for testing
class _ThreadLocalContext:
def init(self):
self.runtime_context = None
_THREAD_LOCAL_CONTEXT = _ThreadLocalContext()
from marimo._plugins.ui._impl.table import get_default_table_max_columns
unit tests
--- Basic Test Cases ---
def test_returns_default_when_context_not_initialized():
"""
Test that the function returns DEFAULT_MAX_COLUMNS when context is not initialized.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = None
codeflash_output = get_default_table_max_columns() # 1.56μs -> 866ns (79.8% faster)
def test_returns_configured_value():
"""
Test that the function returns the value from context config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(10)
codeflash_output = get_default_table_max_columns() # 1.30μs -> 705ns (84.4% faster)
def test_returns_configured_value_with_different_number():
"""
Test with a different number in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(123)
codeflash_output = get_default_table_max_columns() # 1.32μs -> 723ns (83.3% faster)
--- Edge Test Cases ---
def test_configured_value_zero():
"""
Test with zero as the configured value.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(0)
codeflash_output = get_default_table_max_columns() # 1.22μs -> 674ns (81.0% faster)
def test_configured_value_negative():
"""
Test with a negative value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(-5)
codeflash_output = get_default_table_max_columns() # 1.20μs -> 560ns (115% faster)
def test_configured_value_large():
"""
Test with a very large value in the config.
"""
large_value = 999_999
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(large_value)
codeflash_output = get_default_table_max_columns() # 1.29μs -> 666ns (94.4% faster)
def test_configured_value_is_max_int():
"""
Test with Python's max int value.
"""
import sys
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(sys.maxsize)
codeflash_output = get_default_table_max_columns() # 1.18μs -> 650ns (81.4% faster)
def test_configured_value_is_min_int():
"""
Test with Python's min int value.
"""
import sys
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(-sys.maxsize - 1)
codeflash_output = get_default_table_max_columns() # 1.24μs -> 678ns (82.9% faster)
def test_configured_value_is_float():
"""
Test with a float value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(42.5)
codeflash_output = get_default_table_max_columns() # 1.29μs -> 680ns (89.6% faster)
def test_configured_value_is_string():
"""
Test with a string value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext("abc")
codeflash_output = get_default_table_max_columns() # 1.27μs -> 657ns (94.1% faster)
def test_configured_value_is_none():
"""
Test with None value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(None)
codeflash_output = get_default_table_max_columns() # 1.24μs -> 668ns (85.0% faster)
def test_configured_value_is_list():
"""
Test with a list value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext([1,2,3])
codeflash_output = get_default_table_max_columns() # 1.25μs -> 643ns (93.8% faster)
def test_configured_value_is_dict():
"""
Test with a dict value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext({"foo": "bar"})
codeflash_output = get_default_table_max_columns() # 1.26μs -> 675ns (86.8% faster)
def test_configured_value_is_bool_true():
"""
Test with True value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(True)
codeflash_output = get_default_table_max_columns() # 1.28μs -> 587ns (118% faster)
def test_configured_value_is_bool_false():
"""
Test with False value in the config.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(False)
codeflash_output = get_default_table_max_columns() # 1.24μs -> 653ns (89.9% faster)
--- Large Scale Test Cases ---
def test_many_context_switches():
"""
Test switching context values many times to ensure stability.
"""
for i in range(1000): # 1000 context switches
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(i)
codeflash_output = get_default_table_max_columns() # 337μs -> 179μs (88.3% faster)
# Reset context to None at end
_THREAD_LOCAL_CONTEXT.runtime_context = None
codeflash_output = get_default_table_max_columns() # 336ns -> 178ns (88.8% faster)
def test_large_data_structure_in_config():
"""
Test with a large list as the config value.
"""
large_list = list(range(1000))
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(large_list)
codeflash_output = get_default_table_max_columns() # 1.61μs -> 885ns (82.4% faster)
def test_large_string_in_config():
"""
Test with a large string as the config value.
"""
large_string = "x" * 1000
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(large_string)
codeflash_output = get_default_table_max_columns() # 1.06μs -> 588ns (80.6% faster)
def test_large_dict_in_config():
"""
Test with a large dict as the config value.
"""
large_dict = {str(i): i for i in range(1000)}
_THREAD_LOCAL_CONTEXT.runtime_context = DummyContext(large_dict)
codeflash_output = get_default_table_max_columns() # 1.32μs -> 730ns (81.4% faster)
def test_context_not_initialized_after_large_scale():
"""
Ensure the function still returns default after large scale tests and context is None.
"""
_THREAD_LOCAL_CONTEXT.runtime_context = None
codeflash_output = get_default_table_max_columns() # 1.32μs -> 602ns (119% faster)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from marimo._plugins.ui._impl.table import get_default_table_max_columns
def test_get_default_table_max_columns():
get_default_table_max_columns()
🔎 Concolic Coverage Tests and Runtime
codeflash_concolic_bps3n5s8/tmpg28jb6qh/test_concolic_coverage.py::test_get_default_table_max_columnsTo edit these changes
git checkout codeflash/optimize-get_default_table_max_columns-mhvcr6e1and push.