⚡️ Speed up function get_local_contexts by 239%
#58
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.
📄 239% (2.39x) speedup for
get_local_contextsingradio/component_meta.py⏱️ Runtime :
1.63 milliseconds→482 microseconds(best of139runs)📝 Explanation and details
The optimization eliminates a repeated import cost by moving the
from gradio.context import LocalContextstatement from inside the function to module scope. This simple change provides a 238% speedup because:Key Performance Issue: The original code performs a module import and attribute lookup on every function call. The line profiler shows this import taking 49.8% of the total execution time (1.92ms out of 3.86ms total).
Optimization Applied: By caching
LocalContextas_LocalContextat module scope, we eliminate the repeated import overhead. The optimized version shows the import cost is completely removed from the function execution path.Why This Matters: Looking at the function references,
get_local_contexts()is called from theupdateabledecorator wrapper, which is applied to component constructors. This means the function executes every time a Gradio component is created or updated, making it a hot path where even microsecond improvements compound significantly.Performance Characteristics: The test results show consistent 100-250% speedups across all scenarios:
Impact on Workloads: Since this function is in the component creation/update path, applications that create many components or frequently update them will see the most benefit. The optimization maintains identical behavior while reducing overhead in what appears to be a frequently-called utility function.
The optimization is particularly effective because Python's import mechanism involves dictionary lookups and module loading checks that add significant overhead when repeated thousands of times.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
from future import annotations
import sys
import types
imports
import pytest
from gradio.component_meta import get_local_contexts
----------------- Basic Test Cases -----------------
def test_defaults_basic():
"""
Test default output when nothing is set.
Should return (False, False).
"""
codeflash_output = get_local_contexts(); result = codeflash_output # 3.19μs -> 995ns (221% faster)
def test_in_event_listener_true():
"""
Test when in_event_listener is set to True.
Should return (True, False).
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set(True)
# renderable is still unset
codeflash_output = get_local_contexts(); result = codeflash_output # 1.75μs -> 831ns (111% faster)
def test_renderable_true():
"""
Test when renderable is set to a non-None value.
Should return (False, True).
"""
from gradio.context import LocalContext
LocalContext.renderable.set("something")
# in_event_listener is still unset
codeflash_output = get_local_contexts(); result = codeflash_output # 1.83μs -> 745ns (146% faster)
def test_both_true():
"""
Test when both in_event_listener and renderable are set.
Should return (True, True).
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set(True)
LocalContext.renderable.set(object())
codeflash_output = get_local_contexts(); result = codeflash_output # 1.66μs -> 742ns (123% faster)
def test_both_false_explicit():
"""
Test when both in_event_listener and renderable are explicitly set to False/None.
Should return (False, False).
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set(False)
LocalContext.renderable.set(None)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.64μs -> 779ns (111% faster)
----------------- Edge Test Cases -----------------
def test_in_event_listener_non_bool():
"""
Test when in_event_listener is set to a non-bool value (e.g., string).
Should return ('yes', False).
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set("yes")
codeflash_output = get_local_contexts(); result = codeflash_output # 1.65μs -> 796ns (107% faster)
def test_renderable_set_to_false():
"""
Test when renderable is set to False (not None).
Should return (False, True) because False is not None.
"""
from gradio.context import LocalContext
LocalContext.renderable.set(False)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.92μs -> 764ns (151% faster)
def test_in_event_listener_none():
"""
Test when in_event_listener is set to None.
Should return (None, False).
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set(None)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.64μs -> 818ns (100% faster)
def test_renderable_empty_string():
"""
Test when renderable is set to an empty string.
Should return (False, True).
"""
from gradio.context import LocalContext
LocalContext.renderable.set("")
codeflash_output = get_local_contexts(); result = codeflash_output # 1.82μs -> 731ns (148% faster)
def test_contexts_reset():
"""
Test that after setting and resetting, the function returns defaults.
"""
from gradio.context import LocalContext
LocalContext.in_event_listener.set(True)
LocalContext.renderable.set("abc")
# Now reset
LocalContext.in_event_listener.set(None)
LocalContext.renderable.set(None)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.64μs -> 777ns (111% faster)
----------------- Large Scale Test Cases -----------------
def test_many_context_changes():
"""
Test the function with many rapid changes to contextvars.
Ensures that the latest value is always returned.
"""
from gradio.context import LocalContext
for i in range(100):
LocalContext.in_event_listener.set(i % 2 == 0)
LocalContext.renderable.set(i)
expected = (i % 2 == 0, True)
codeflash_output = get_local_contexts(); result = codeflash_output # 69.1μs -> 19.9μs (247% faster)
# Reset to default at the end
LocalContext.in_event_listener.set(None)
LocalContext.renderable.set(None)
def test_large_non_none_renderable():
"""
Test with a large object as renderable (e.g., a long string).
Should still return True for renderable.
"""
from gradio.context import LocalContext
long_str = "x" * 999
LocalContext.renderable.set(long_str)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.83μs -> 734ns (149% faster)
def test_large_number_of_set_and_get():
"""
Stress test: set and get contextvars many times to ensure no memory leaks or stale state.
"""
from gradio.context import LocalContext
for i in range(500):
LocalContext.in_event_listener.set(i)
LocalContext.renderable.set(None if i % 2 == 0 else i)
expected = (i, False if i % 2 == 0 else True)
codeflash_output = get_local_contexts(); result = codeflash_output # 337μs -> 96.6μs (249% faster)
def test_large_scale_defaults():
"""
Ensure that after a large number of contextvar changes, resetting to default works.
"""
from gradio.context import LocalContext
for i in range(300):
LocalContext.in_event_listener.set(True)
LocalContext.renderable.set("test")
# Reset
LocalContext.in_event_listener.set(None)
LocalContext.renderable.set(None)
codeflash_output = get_local_contexts(); result = codeflash_output # 1.48μs -> 761ns (94.3% faster)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from future import annotations
import sys
import types
imports
import pytest
from gradio.component_meta import get_local_contexts
--- Begin test code ---
We'll need to create a mock for gradio.context.LocalContext for testing.
Since we are not allowed to use pytest-mock or similar, we'll monkeypatch sys.modules directly.
class DummyContextVar:
"""
A dummy context variable to simulate the ContextVar API used in LocalContext.
"""
def init(self, default=None):
self.value = default
self.was_set = False
class DummyLocalContext:
"""
Dummy LocalContext class with in_event_listener and renderable attributes as context variables.
"""
in_event_listener = DummyContextVar()
renderable = DummyContextVar()
------------------- BASIC TEST CASES -------------------
def test_default_contexts():
"""
Test default behavior when nothing is set.
Should return (False, False).
"""
# Ensure no value is set
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
codeflash_output = get_local_contexts(); result = codeflash_output # 3.60μs -> 1.01μs (255% faster)
def test_in_event_listener_true_renderable_false():
"""
Test when in_event_listener is set to True, renderable is not set.
Should return (True, False).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.in_event_listener.set(True)
DummyLocalContext.renderable = DummyContextVar()
codeflash_output = get_local_contexts(); result = codeflash_output # 3.31μs -> 986ns (236% faster)
def test_in_event_listener_false_renderable_true():
"""
Test when in_event_listener is False (set), renderable is set to a non-None value.
Should return (False, True).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.in_event_listener.set(False)
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set("some_value")
codeflash_output = get_local_contexts(); result = codeflash_output # 3.31μs -> 952ns (247% faster)
def test_in_event_listener_true_renderable_true():
"""
Test when both in_event_listener and renderable are set to True/non-None.
Should return (True, True).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.in_event_listener.set(True)
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set(object())
codeflash_output = get_local_contexts(); result = codeflash_output # 3.27μs -> 1.00μs (227% faster)
------------------- EDGE TEST CASES -------------------
def test_renderable_explicitly_set_to_none():
"""
Test when renderable is explicitly set to None.
The function should return (False, False).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set(None)
codeflash_output = get_local_contexts(); result = codeflash_output # 3.15μs -> 985ns (220% faster)
def test_in_event_listener_set_to_false_explicitly():
"""
Test when in_event_listener is explicitly set to False.
Should still return (False, False) if renderable is not set.
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.in_event_listener.set(False)
DummyLocalContext.renderable = DummyContextVar()
codeflash_output = get_local_contexts(); result = codeflash_output # 3.24μs -> 998ns (225% faster)
def test_renderable_set_to_empty_string():
"""
Test when renderable is set to an empty string (which is not None).
Should return (False, True).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set("")
codeflash_output = get_local_contexts(); result = codeflash_output # 3.12μs -> 958ns (226% faster)
def test_renderable_set_to_false():
"""
Test when renderable is set to False (which is not None).
Should return (False, True).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set(False)
codeflash_output = get_local_contexts(); result = codeflash_output # 3.14μs -> 940ns (234% faster)
def test_in_event_listener_set_to_non_bool_value():
"""
Test when in_event_listener is set to a non-bool value (e.g., 123).
Should return (123, False).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.in_event_listener.set(123)
DummyLocalContext.renderable = DummyContextVar()
codeflash_output = get_local_contexts(); result = codeflash_output # 3.18μs -> 922ns (245% faster)
def test_renderable_set_to_object():
"""
Test when renderable is set to an object instance.
Should return (False, True).
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.renderable.set({})
codeflash_output = get_local_contexts(); result = codeflash_output # 3.11μs -> 955ns (226% faster)
------------------- LARGE SCALE TEST CASES -------------------
def test_many_context_changes():
"""
Simulate changing context variables many times and ensure latest value is respected.
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
# Set and reset values multiple times
for i in range(100):
DummyLocalContext.in_event_listener.set(i % 2 == 0)
DummyLocalContext.renderable.set(i)
# Final set
DummyLocalContext.in_event_listener.set(True)
DummyLocalContext.renderable.set("final")
codeflash_output = get_local_contexts(); result = codeflash_output # 3.31μs -> 921ns (259% faster)
def test_large_number_of_contexts():
"""
Test with a large number of DummyLocalContext instances to ensure no cross-talk.
"""
# Simulate 500 different contexts
contexts = []
for i in range(500):
ctx = types.SimpleNamespace()
ctx.in_event_listener = DummyContextVar()
ctx.renderable = DummyContextVar()
ctx.in_event_listener.set(i % 2 == 0)
ctx.renderable.set(i if i % 3 == 0 else None)
contexts.append(ctx)
# Patch LocalContext for each context and test
for idx, ctx in enumerate(contexts):
DummyLocalContext.in_event_listener = ctx.in_event_listener
DummyLocalContext.renderable = ctx.renderable
expected = (idx % 2 == 0, idx % 3 == 0)
codeflash_output = get_local_contexts(); result = codeflash_output # 333μs -> 98.4μs (239% faster)
def test_performance_under_load():
"""
Test that get_local_contexts runs efficiently under a burst of calls.
"""
DummyLocalContext.in_event_listener = DummyContextVar()
DummyLocalContext.renderable = DummyContextVar()
DummyLocalContext.in_event_listener.set(True)
DummyLocalContext.renderable.set("busy")
# Call function 1000 times
for _ in range(1000):
codeflash_output = get_local_contexts(); result = codeflash_output # 648μs -> 190μs (241% faster)
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
⏪ Replay Tests and Runtime
test_pytest_testtest_components_py_testcomponentstest_audio_py_testcomponentstest_file_py_testcomponentst__replay_test_0.py::test_gradio_component_meta_get_local_contextsTo edit these changes
git checkout codeflash/optimize-get_local_contexts-mhv5g83band push.