-
Notifications
You must be signed in to change notification settings - Fork 367
Have rerun render shared memory topics (fix dev for MacOS) #1716
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
base: dev
Are you sure you want to change the base?
Changes from all commits
07d91df
8cc2dcf
0100d20
b7f0d64
465e553
bae41e5
073df16
4ba103f
0d658f0
d6dc23b
3d20c0c
bbd148f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -23,7 +23,7 @@ | |||||||||
| import struct | ||||||||||
| import threading | ||||||||||
| import time | ||||||||||
| from typing import TYPE_CHECKING, Any | ||||||||||
| from typing import TYPE_CHECKING, Any, Literal | ||||||||||
| import uuid | ||||||||||
|
|
||||||||||
| import numpy as np | ||||||||||
|
|
@@ -104,14 +104,14 @@ def __init__( | |||||||||
| self, | ||||||||||
| *, | ||||||||||
| prefer: str = "auto", | ||||||||||
| default_capacity: int = 3686400, | ||||||||||
| default_capacity: int | None = None, | ||||||||||
| close_channels_on_stop: bool = True, | ||||||||||
| **_: Any, | ||||||||||
| ) -> None: | ||||||||||
| super().__init__() | ||||||||||
| self.config = SharedMemoryConfig( | ||||||||||
| prefer=prefer, | ||||||||||
| default_capacity=default_capacity, | ||||||||||
| default_capacity=default_capacity or SharedMemoryConfig.default_capacity, | ||||||||||
| close_channels_on_stop=close_channels_on_stop, | ||||||||||
| ) | ||||||||||
| self._topics: dict[str, SharedMemoryPubSubBase._TopicState] = {} | ||||||||||
|
|
@@ -305,6 +305,80 @@ class PickleSharedMemory( | |||||||||
| ... | ||||||||||
|
|
||||||||||
|
|
||||||||||
| # QUALITY_LEVEL: temporary (out of [deprecated, temporary, experimental, sufficient, robust]) | ||||||||||
| class ShmSubset: | ||||||||||
| """Subscribe-all adapter for a fixed set of shared-memory topics. | ||||||||||
|
|
||||||||||
| Stop-gap for the Rerun bridge: SHM pubsub has no topic discovery, so the | ||||||||||
| bridge can't ``subscribe_all`` like it does with LCM. This class wraps | ||||||||||
| known SHM topics so they can be passed in the bridge's ``pubsubs`` list. | ||||||||||
| Replace once the bridge auto-discovers active transports from blueprint wiring. | ||||||||||
|
|
||||||||||
| Wraps PickleSharedMemory or BytesSharedMemory and exposes the | ||||||||||
| ``subscribe_all`` interface so it can be used in the bridge's ``pubsubs`` | ||||||||||
| list alongside LCM. | ||||||||||
|
|
||||||||||
| Example:: | ||||||||||
|
|
||||||||||
| from dimos.protocol.pubsub.impl.shmpubsub import ShmSubset | ||||||||||
|
|
||||||||||
| bridge = RerunBridgeModule( | ||||||||||
| pubsubs=[LCM(), ShmSubset(topics=[("color_image", 6220800, "pickle")])], | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The example topic name is
Suggested change
|
||||||||||
| ) | ||||||||||
|
|
||||||||||
| Each topic entry is ``(name, capacity, encoding)`` where encoding is | ||||||||||
| ``"pickle"`` (for pSHMTransport / PickleSharedMemory) or | ||||||||||
| ``"bytes"`` (for SHMTransport / BytesSharedMemory). | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| def __init__(self, topics: list[tuple[str, int, Literal["pickle", "bytes"]]]) -> None: | ||||||||||
| self._topic_specs = topics | ||||||||||
| self._shm_instances: list[SharedMemoryPubSubBase] = [] | ||||||||||
| self._unsubs: list[Callable[[], None]] = [] | ||||||||||
|
|
||||||||||
| def start(self) -> None: | ||||||||||
| pass # instances are started lazily in subscribe_all | ||||||||||
|
|
||||||||||
| def stop(self) -> None: | ||||||||||
| for unsub in self._unsubs: | ||||||||||
| unsub() | ||||||||||
| self._unsubs.clear() | ||||||||||
| for shm in self._shm_instances: | ||||||||||
| shm.stop() | ||||||||||
| self._shm_instances.clear() | ||||||||||
|
|
||||||||||
| def subscribe_all(self, callback: Callable[[Any, Any], Any]) -> Callable[[], None]: | ||||||||||
| try: | ||||||||||
| for topic_name, capacity, encoding in self._topic_specs: | ||||||||||
| if encoding == "pickle": | ||||||||||
| shm: SharedMemoryPubSubBase = PickleSharedMemory(default_capacity=capacity) | ||||||||||
| elif encoding == "bytes": | ||||||||||
| shm = BytesSharedMemory(default_capacity=capacity) | ||||||||||
| else: | ||||||||||
| logger.error( | ||||||||||
| f"ShmSubset: unknown encoding '{encoding}', skipping topic '{topic_name}'" | ||||||||||
| ) | ||||||||||
| continue | ||||||||||
| shm.start() | ||||||||||
| self._shm_instances.append(shm) | ||||||||||
|
|
||||||||||
| def _cb(msg: Any, _topic: Any, _tn: str = topic_name) -> None: | ||||||||||
| callback(msg, _tn) | ||||||||||
|
|
||||||||||
| unsub = shm.subscribe(topic_name, _cb) | ||||||||||
| self._unsubs.append(unsub) | ||||||||||
| except Exception: | ||||||||||
| # If a later topic fails (e.g. bad capacity, SHM allocation error), | ||||||||||
| # clean up SHM instances already started for earlier topics. | ||||||||||
| self.stop() | ||||||||||
| raise | ||||||||||
|
|
||||||||||
| def unsubscribe_all() -> None: | ||||||||||
| self.stop() | ||||||||||
|
|
||||||||||
| return unsubscribe_all | ||||||||||
|
|
||||||||||
|
|
||||||||||
| class LCMSharedMemoryPubSubBase(PubSub[Topic, Any]): | ||||||||||
| """SharedMemory pubsub that uses LCM Topic type, delegating to SharedMemoryPubSubBase.""" | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -270,6 +270,8 @@ def _get_entity_path(self, topic: Any) -> str: | |||||||
| topic_str = getattr(topic, "name", None) or str(topic) | ||||||||
| # Strip everything after # (LCM topic suffix) | ||||||||
| topic_str = topic_str.split("#")[0] | ||||||||
| # Ensure / separator between prefix and topic | ||||||||
| assert topic_str.startswith("/"), f"{topic_str} doesn't start with slash" | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| return f"{self.config.entity_prefix}{topic_str}" | ||||||||
|
|
||||||||
| def _on_message(self, msg: Any, topic: Any) -> None: | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the current
__reduce__/__setstate__split, unpicklingpSHMTransport(andSHMTransport) calls__init__first (because__reduce__returns(pSHMTransport, (self.topic,), state)). That__init__call constructs aPickleSharedMemory(default_capacity=None), which is immediately discarded when__setstate__constructs the correct one. This is a minor but unnecessary allocation.One common pattern to avoid this is to delegate to
__new__in__reduce__and perform all initialisation in__setstate__:Or simply accept the redundant allocation as a known trade-off and add a comment. The same applies to
SHMTransport(lines 203-208).