⚡️ Speed up method MarimoComm._publish_msg by 41%
#596
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.
📄 41% (0.41x) speedup for
MarimoComm._publish_msginmarimo/_plugins/ui/_impl/comm.py⏱️ Runtime :
121 microseconds→86.0 microseconds(best of77runs)📝 Explanation and details
The optimized code achieves a 41% speedup through two key optimizations:
1. Import Hoisting (Major Impact)
The most significant optimization moves
from marimo._messaging.ops import SendUIElementMessagefrom inside theflush()method to module scope. The line profiler shows this import was taking 17.5% of flush() runtime (186,800ns out of 1,069,800ns total). By hoisting it to module scope, this cost is eliminated from the hot path, providing substantial savings whenflush()is called frequently.2. Conditional Logic Consolidation (Minor Impact)
The three separate
ifstatements checkingmsg_typeequality are consolidated into a single set membership check:if msg_type in {COMM_OPEN_NAME, COMM_MESSAGE_NAME, COMM_CLOSE_NAME}. This reduces the number of string comparisons from up to 3 down to 1, and eliminates redundant code paths that were executing identical logic.Performance Analysis:
Impact on Workloads:
This optimization is especially valuable for UI-intensive applications where widgets frequently publish messages (open, update, close operations). Since
MarimoCommappears to be part of marimo's UI plugin system, these methods likely execute in hot paths during interactive notebook usage, making the performance gains meaningful for user experience.The optimizations maintain complete behavioral equivalence while eliminating redundant work, making this a safe and effective performance improvement.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
import pytest
from marimo._plugins.ui._impl.comm import MarimoComm
Minimal stubs for dependencies needed by MarimoComm._publish_msg
class DummyLogger:
def init(self):
self.warnings = []
def warning(self, *args):
self.warnings.append(args)
Simulate the MessageBufferData used in MarimoComm
class MessageBufferData:
def init(self, data, metadata, buffers, model_id):
self.data = data
self.metadata = metadata
self.buffers = buffers
self.model_id = model_id
Dummy SendUIElementMessage for flush
class DummySendUIElementMessage:
def init(self, ui_element, model_id, message, buffers):
self.ui_element = ui_element
self.model_id = model_id
self.message = message
self.buffers = buffers
DummySendUIElementMessage.sent.append(self)
def broadcast(self):
DummySendUIElementMessage.broadcasted.append(self)
DummySendUIElementMessage.sent = []
DummySendUIElementMessage.broadcasted = []
Patch marimo_comm flush to use dummy SendUIElementMessage
def dummy_flush(self):
while self._publish_message_buffer:
item = self._publish_message_buffer.pop(0)
DummySendUIElementMessage(
ui_element=self.ui_element_id,
model_id=item.model_id,
message=item.data,
buffers=item.buffers,
).broadcast()
Dummy comm manager for registration
class DummyCommManager:
def init(self):
self.registered = []
self.unregistered = []
def register_comm(self, comm):
self.registered.append(comm)
def unregister_comm(self, comm):
self.unregistered.append(comm)
from marimo._plugins.ui._impl.comm import MarimoComm
@pytest.fixture
def comm():
# Provide a fresh MarimoComm for each test
comm_manager = DummyCommManager()
return MarimoComm(
comm_id="test_model_id",
comm_manager=comm_manager,
target_name="target",
)
1. BASIC TEST CASES
def test_publish_open_message_basic(comm):
"""Test publishing a basic COMM_OPEN message with simple data."""
comm._publish_msg(
comm.COMM_OPEN_NAME,
data={"foo": 1},
metadata={"bar": 2},
buffers=[b"abc"]
)
sent = DummySendUIElementMessage.sent[0]
def test_publish_comm_message_basic(comm):
"""Test publishing a basic COMM_MESSAGE message with no data."""
comm._publish_msg(comm.COMM_MESSAGE_NAME)
sent = DummySendUIElementMessage.sent[0]
def test_publish_close_message_basic(comm):
"""Test publishing a basic COMM_CLOSE message."""
comm._publish_msg(comm.COMM_CLOSE_NAME, data={"baz": 42})
sent = DummySendUIElementMessage.sent[0]
def test_publish_multiple_messages(comm):
"""Test publishing multiple messages in sequence."""
comm._publish_msg(comm.COMM_OPEN_NAME, data={"a": 1})
comm._publish_msg(comm.COMM_MESSAGE_NAME, data={"b": 2})
comm._publish_msg(comm.COMM_CLOSE_NAME, data={"c": 3})
2. EDGE TEST CASES
def test_publish_msg_with_none_values(comm):
"""Test that None data/metadata/buffers are replaced with defaults."""
comm._publish_msg(comm.COMM_OPEN_NAME, data=None, metadata=None, buffers=None)
sent = DummySendUIElementMessage.sent[0]
def test_publish_msg_with_empty_dicts_and_lists(comm):
"""Test that empty dicts/lists are preserved as is."""
comm._publish_msg(comm.COMM_MESSAGE_NAME, data={}, metadata={}, buffers=[])
sent = DummySendUIElementMessage.sent[0]
def test_publish_msg_with_large_buffer(comm):
"""Test that large buffer is handled correctly."""
big_buffer = [b"x" * 1024] * 10 # 10 KB total
comm._publish_msg(comm.COMM_OPEN_NAME, buffers=big_buffer)
sent = DummySendUIElementMessage.sent[0]
def test_publish_msg_with_unusual_types(comm):
"""Test that non-string keys and values in data/metadata are handled."""
class Weird:
def eq(self, other): return True
data = {42: Weird()}
metadata = {None: [1, 2, 3]}
comm._publish_msg(comm.COMM_MESSAGE_NAME, data=data, metadata=metadata)
sent = DummySendUIElementMessage.sent[0]
def test_publish_msg_with_extra_kwargs(comm):
"""Test that extra kwargs are ignored."""
comm._publish_msg(comm.COMM_OPEN_NAME, data={"x": 1}, extra1=123, extra2="abc")
sent = DummySendUIElementMessage.sent[0]
3. LARGE SCALE TEST CASES
def test_publish_msg_many_messages(comm):
"""Test publishing many messages in quick succession."""
for i in range(100):
comm._publish_msg(comm.COMM_MESSAGE_NAME, data={"i": i})
def test_publish_msg_large_data_and_metadata(comm):
"""Test with both large data and metadata."""
data = {str(i): i for i in range(500)}
metadata = {str(i): -i for i in range(500)}
comm._publish_msg(comm.COMM_MESSAGE_NAME, data=data, metadata=metadata)
sent = DummySendUIElementMessage.sent[0]
codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
from typing import Any, Callable, Optional
imports
import pytest
from marimo._plugins.ui._impl.comm import MarimoComm
--- Minimal stubs and helpers to make the test self-contained ---
class DummyLogger:
def init(self):
self.last_warning = []
class DummySendUIElementMessage:
# records all calls for inspection
calls = []
def init(self, ui_element, model_id, message, buffers):
self.ui_element = ui_element
self.model_id = model_id
self.message = message
self.buffers = buffers
DummySendUIElementMessage.calls.append(self)
Patch for marimo_logger and MessageBufferData
LOGGER = DummyLogger()
Constants as in the real code
COMM_MESSAGE_NAME = "marimo_comm_msg"
COMM_OPEN_NAME = "marimo_comm_open"
COMM_CLOSE_NAME = "marimo_comm_close"
--- MarimoComm minimal stub for testing ---
class DummyCommManager:
def register_comm(self, comm): pass
def unregister_comm(self, comm): pass
@pytest.fixture
def comm():
# Provide a fresh MarimoComm for each test
return MarimoComm(
comm_id="test_id",
comm_manager=DummyCommManager(),
target_name="test_target"
)
---------------- BASIC TEST CASES ----------------
def test_publish_msg_multiple_calls(comm):
"""Test multiple sequential publish_msg calls."""
comm._publish_msg(COMM_OPEN_NAME, data={"x": 1}) # 5.58μs -> 4.41μs (26.7% faster)
comm._publish_msg(COMM_MESSAGE_NAME, data={"y": 2}) # 2.86μs -> 2.12μs (34.9% faster)
comm._publish_msg(COMM_CLOSE_NAME, data={"z": 3}) # 2.23μs -> 1.71μs (30.4% faster)
---------------- EDGE TEST CASES ----------------
def test_publish_msg_buffers_mutation(comm):
"""Test that buffers passed in are not mutated by the function."""
buffers = [b"a", b"b"]
comm._publish_msg(COMM_MESSAGE_NAME, buffers=buffers) # 5.53μs -> 4.39μs (26.0% faster)
def test_publish_msg_many_sequential_calls(comm):
"""Test many sequential publish_msg calls."""
for i in range(50):
comm._publish_msg(COMM_MESSAGE_NAME, data={"i": i}) # 105μs -> 73.4μs (43.3% faster)
for idx, call in enumerate(DummySendUIElementMessage.calls):
pass
#------------------------------------------------
*** Begin Not Deterministic Debug ***
Previous iteration: 1
Current SMT expression: comm_id_3len_4 != comm_id_3len_4
Current stack tail:
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/libimpl/builtinslib.py:2785
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/libimpl/builtinslib.py:3510
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:24
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:113
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:104
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/enforce.py:43
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:498
proxy_arg_self.py:705
Previous stack tail:
proxy_arg_msg_type.py:698
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:755
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:1375
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/path_cover.py:130
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:773
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:930
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:969
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:8
Reason: Wrong node type (is ParallelNode, expected WorstResultNode)
*** End Not Deterministic Debug ***
*** Begin Not Deterministic Debug ***
Previous iteration: 68
Current SMT expression: comm_id_3len_4 != comm_id_3len_4
Current stack tail:
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/libimpl/builtinslib.py:2785
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/libimpl/builtinslib.py:3510
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:24
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:113
/home/ubuntu/work/repo/marimo/_plugins/ui/_impl/comm.py:104
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/enforce.py:43
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:498
proxy_arg_self.py:705
Previous stack tail:
proxy_arg_msg_type.py:698
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:755
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/core.py:1375
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/path_cover.py:130
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:773
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:930
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:969
/home/ubuntu/work/repo/.venv/lib/python3.10/site-packages/crosshair/main.py:8
Reason: Wrong node type (is ParallelNode, expected WorstResultNode)
*** End Not Deterministic Debug ***
from marimo._plugins.ui._impl.comm import MarimoComm
from marimo._plugins.ui._impl.comm import MarimoCommManager
def test_MarimoComm__publish_msg():
MarimoComm._publish_msg(MarimoComm('', MarimoCommManager(), '', data={'': ''}, metadata=None, buffers=None, =0), 'marimo_comm_close', data={}, metadata=None, buffers=None)
def test_MarimoComm__publish_msg_2():
MarimoComm._publish_msg(MarimoComm('', MarimoCommManager(), '', data={}, metadata=None, buffers=[]), 'marimo_comm_open', data=None, metadata={}, buffers=[b''])
def test_MarimoComm__publish_msg_3():
MarimoComm._publish_msg(MarimoComm('', MarimoCommManager(), '', data=None, metadata={}, buffers=None), 'marimo_comm_msg', data=None, metadata=None, buffers=None)
def test_MarimoComm__publish_msg_4():
MarimoComm._publish_msg(MarimoComm('', MarimoCommManager(), '', data=None, metadata={}, buffers=[], =''), '', data=None, metadata={'': ''}, buffers=None)
To edit these changes
git checkout codeflash/optimize-MarimoComm._publish_msg-mhv6d2t5and push.