How to Tune DimOS Performance Using n_workers and Shared Memory (SHM) Transports
Increase n_workers to parallelize module execution and switch high‑bandwidth streams to pSHMTransport or SHMTransport to eliminate network stack overhead and minimize latency in dimensionalOS/dimos pipelines.
DimOS is a modular robotics framework where every module runs in an isolated worker process. To achieve maximum throughput on multi‑core hardware, you must balance CPU parallelism via the n_workers configuration with zero‑copy inter‑process communication using shared‑memory transports. This guide explains how to configure both mechanisms based on the actual implementation in the dimensionalOS/dimos repository.
Understanding the Worker Model in DimOS
DimOS spawns a pool of worker processes at runtime to execute module code. The global singleton GlobalConfig defines the default concurrency level in dimos/core/global_config.py:
# dimos/core/global_config.py (lines 38-39)
n_workers: int = 2 # Default worker count
When a blueprint is instantiated, the WorkerManager class creates the requested number of Worker processes and manages their lifecycle in dimos/core/worker_manager.py (lines 30‑45). The manager distributes incoming module requests across the pool using WorkerManager._select_worker(), ensuring load is balanced across available CPU cores.
Configuring n_workers for Optimal Concurrency
Setting Workers in a Blueprint
Blueprints declare their resource requirements via the global_config decorator. Override the default n_workers value to match your hardware:
from dimos.core.global_config import global_config
@global_config(n_workers=8) # Use 8 workers for high-throughput pipelines
def my_high_performance_blueprint():
return autoconnect().with_modules([...])
Runtime Override via CLI
You can adjust worker count without modifying source code using the DimOS CLI. The --n-workers flag is parsed in dimos/robot/cli/dimos.py (lines 180‑182) and injected into GlobalConfig before the coordinator starts:
dimos run unitree_go2_basic --n-workers 6
This command spawns six workers instead of the blueprint’s default, useful for temporary scaling on larger machines.
Eliminating Bottlenecks with Shared Memory Transports
Why Shared Memory Outperforms Network Transports
By default, DimOS uses LCMTransport (UDP multicast) for inter‑module messaging. While efficient for small control signals, UDP introduces serialization overhead and kernel networking stack latency when streaming large binary data like camera frames or LiDAR point clouds.
The POSIX shared‑memory transports (pSHMTransport and SHMTransport) bypass the network stack entirely. The sender writes data directly into a memory‑mapped segment, and the receiver accesses it via a single memcpy operation. This eliminates sendto/recvfrom system calls and reduces CPU usage significantly.
Available SHM Transport Options
DimOS provides four transport implementations in dimos/core/transport.py:
| Transport | Implementation | Best For |
|---|---|---|
pSHMTransport |
Pickled objects in POSIX SHM (lines 60‑77) | High‑bandwidth sensor messages (sensor_msgs.Image) where Python pickling is acceptable |
SHMTransport |
Raw bytes in POSIX SHM (lines 90‑107) | Raw binary payloads (point clouds) requiring maximum throughput |
JpegShmTransport |
JPEG‑compressed images in SHM | Bandwidth‑constrained wireless links |
LCMTransport |
UDP multicast LCM | Small control messages, cross‑machine communication |
Configuring Shared Memory in Blueprints
Attach transports to specific topics using the autoconnect().transports(dict) API. The dictionary maps (topic_name, message_type) tuples to transport instances:
from dimos.core.transport import SHMTransport, pSHMTransport
from dimos.msgs.sensor_msgs import PointCloud2, Image
# Configure SHM for high-bandwidth streams
shm_transports = {
("lidar/points", PointCloud2): SHMTransport("lidar_points"), # Raw bytes
("camera/image", Image): pSHMTransport("camera_image"), # Pickled Image msgs
}
blueprint = autoconnect().transports(shm_transports)
As shown in dimos/robot/unitree/go2/blueprints/basic/unitree_go2_basic.py (lines 30‑41), the framework automatically selects pSHMTransport on macOS platforms where high‑bandwidth UDP is unreliable, demonstrating the same pattern:
# From unitree_go2_basic.py - platform-specific transport selection
if platform.system() == "Darwin":
# Use shared memory on macOS for high-bandwidth streams
transports = {(...): pSHMTransport(...)}
Practical Performance Tuning Scenarios
High-Bandwidth Camera Streams
For 30 FPS 1080p image processing:
- Set
n_workers=4to parallelize image decoding, perception, and control - Use
pSHMTransportforsensor_msgs.Imagetopics to avoid UDP bottlenecks - Ensure workers are pinned to separate CPU cores if the OS supports affinity
Dense LiDAR Point Clouds
For high-frequency lidar data:
- Allocate
n_workers=8on a 16-core workstation to isolate the sensor driver and mapping modules - Configure
SHMTransport(raw bytes) forPointCloud2messages indimos/core/transport.py(lines 90‑107) - Place the producer and consumer on different workers to maximize parallel processing
Runtime Adjustment
Temporary scaling without code changes:
# Scale workers for a heavy inference workload
dimos run my_blueprint --n-workers 12
Summary
- Worker Scaling: DimOS defaults to
n_workers=2defined indimos/core/global_config.py; increase this value via the@global_configdecorator or the--n-workersCLI flag to parallelize module execution across CPU cores. - Shared Memory Transports: Replace
LCMTransportwithpSHMTransport(pickled objects) orSHMTransport(raw bytes) fromdimos/core/transport.pyto eliminate UDP overhead for large binary streams like images and point clouds. - Configuration Pattern: Use
autoconnect().transports({(topic, type): Transport(...)})to bind high‑bandwidth topics to SHM transports while keeping control signals on LCM for cross‑machine compatibility. - Hardware Alignment: Match
n_workersto physical core count; use 4‑8 workers for high‑throughput sensor processing and 8‑16 for dense perception pipelines on workstation‑class hardware.
Frequently Asked Questions
What is the default number of workers in DimOS and where is it defined?
The default is 2 workers, defined in dimos/core/global_config.py at lines 38‑39 as the n_workers field of the GlobalConfig class. This value is instantiated when the DimOS coordinator starts and creates the WorkerManager pool.
How do I switch from UDP to shared memory for a specific topic?
Use the transports method of the autoconnect() builder. Create a dictionary mapping (topic_name, message_type) tuples to SHMTransport or pSHMTransport instances, then pass it to autoconnect().transports(your_dict). This overrides the default LCMTransport for those specific streams while leaving others unchanged.
When should I use pSHMTransport versus SHMTransport?
Choose pSHMTransport when streaming picklable Python objects like sensor_msgs.Image or structured sensor messages where the convenience of pickle serialization outweighs the slight overhead. Choose SHMTransport for raw binary payloads like dense LiDAR point clouds or uncompressed depth maps where you need maximum throughput and minimal serialization CPU usage.
Can I change the worker count without modifying my blueprint code?
Yes. Use the --n-workers command‑line flag when launching your DimOS application. The CLI handler in dimos/robot/cli/dimos.py (lines 180‑182) parses this argument and injects the value into GlobalConfig.n_workers before the coordinator initializes the WorkerManager, allowing temporary scaling for specific hardware or workload demands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →