HORUS Benchmarks
Performance validation with real-world robotics workloads.
Benchmark Methodology
Measurement Approach
- Statistical sampling: Criterion.rs micro-benchmarks, sample sizes 10-1000 depending on the group
- Confidence intervals: Bootstrap 95% CI with Tukey IQR outlier detection
- Controlled methodology: 2-10s measurement windows per group, Criterion's default 3s warm-up
- Standalone binaries: 20,000-1,000,000 samples per scenario depending on the binary;
all_paths_latency,robotics_messages_benchmark,determinism_benchmarkandcross_process_benchmarkare RDTSC-timed with calibrated overhead subtraction,topic_probeusesCLOCK_MONOTONIC(producer and consumer are threads in one process, so it is offset-free by construction) - Comprehensive coverage: 4 robotics message types, 10 backend routes
Workload Testing
- Real workloads: Control loops, sensor fusion, manipulator commands, lidar scans
- Scale testing: node counts 0-20 and background-topic counts 0-10 (
scheduler_ipc_latency); 1-8 producers and 1-8 consumers (scalability_benchmark,all_paths_latencystress scenarios) - Topology coverage: Same-thread, cross-thread and cross-process, 1:1 through N:N
- Contention: Multi-producer and multi-consumer paths measured under contention
Executive Summary
send() costs tens of nanoseconds for typical robotics messages.
Measured with robotics_messages_benchmark on an Intel Core i7-10750H (6C/12T, powersave governor), 50,000 iterations per message type after 5,000 warmup iterations — except LaserScan, which runs one fifth of each (10,000 iterations after 1,000 warmup), so its p99 rests on one fifth the samples the other rows do. These are the four message types the benchmark actually runs:
robotics_messages_benchmark times tx.send() enqueue cost only. A
cross-thread consumer drains in the background and no sample waits for
delivery, so these are not end-to-end latencies. The binary says so on every
run:
SUMMARY BY MESSAGE TYPE — send() ENQUEUE COST, not end-to-end latency
An end-to-end control loop additionally pays the receive side, the node's own
compute, and the scheduler's jitter — none of which is measured here. Do not
read a figure below as a control-loop guarantee, and do not divide a control
period by it to get "headroom": the benchmark's own real-time section prints
gate not discriminating on every such comparison for exactly that reason.
For end-to-end numbers see Performance, which reports one-way publish→receive latency.
Measured with robotics_messages_benchmark on an Intel Core i7-10750H (6C/12T,
powersave governor), 50,000 iterations after 5,000 warmup iterations —
except LaserScan, which runs 10,000 (benchmark_laserscan(iterations / 5)).
| Message Type | Size | send() median | send() p99 | Sustained publish rate |
|---|---|---|---|---|
| CmdVel | 16 B | 75 ns | 135 ns | 12.14M msg/s |
| Imu | 304 B | 121 ns | 235 ns | 7.46M msg/s |
| JointCommand | 928 B | 135 ns | 226 ns | 6.89M msg/s |
| LaserScan | 1480 B | 210 ns | 283 ns | 4.42M msg/s |
"Sustained publish rate" is wall-clock over the measured loop, including batch drain-waits. It is the rate this one producer/consumer pair achieved on that host — not a bus capacity, and not additive across publishers.
cargo build --release --bin robotics_messages_benchmark
./target/release/robotics_messages_benchmark
The medians above reproduce, and are conservative: on the same CPU model with
the performance governor, four runs gave medians of 50–82 ns (CmdVel), 64–74 ns
(Imu), 73–115 ns (JointCommand) and 97–194 ns (LaserScan) — at or below the
published figures.
The sustained-rate column did not reproduce. The same four runs peaked at 7.00M (CmdVel), 4.53M (Imu), 3.33M (JointCommand) and 1.46M msg/s (LaserScan) — 1.6x to 3.0x below the table, with the gap widening as messages get larger. Those runs were on a loaded desktop, and this metric is wall-clock, so load depresses it directly; that is enough to explain some of the gap but not obviously all of it. Treat the rate column as an upper bound observed on an idle machine rather than as a figure you should expect to see. Tracked in softmata/horus#176.
Performance Highlights
Key Findings
- Tens of nanoseconds to enqueue a message up to 1.5 KB
- Serde integration works with complex nested structs
- Graceful scaling with message size (predictable, roughly linear in payload)
- Enqueue cost is far below any robotics control period — small enough that it is not the term that decides whether a loop meets its deadline
Production Readiness
- Real-time control: 75 ns to enqueue a CmdVel; the loop's deadline budget is
spent on compute, the receive side and scheduling, not on
send() - Sensor fusion: 304-byte Imu messages enqueue in 121 ns median, 235 ns p99
- Manipulator control: kilobyte-scale JointCommand payloads at 135 ns median
- Multi-robot systems: millions of messages/s from a single producer/consumer pair on one host
Detailed Results
Every figure in this section is send() enqueue cost, as described in the
Executive Summary. "Iterations" is the count that message
type actually runs, which is not the same for all four.
CmdVel (Motor Control Command)
Use Case: Real-time motor control @ 1000Hz Size: 16 bytes
send() median: 75 ns
send() p99: 135 ns
Sustained publish rate: 12.14M msg/s
Iterations: 50,000
Analysis: 16 bytes enqueues in well under a microsecond. At a 1000 Hz control period, send() is a rounding error against the 1 ms budget — the loop's timing is decided by the receive side, the node's compute and the scheduler, not by this number.
Imu (Inertial Measurement Unit)
Use Case: Orientation and acceleration @ 500Hz
Size: 304 bytes (size_of; 296 bytes declared)
send() median: 121 ns
send() p99: 235 ns
Sustained publish rate: 7.46M msg/s
Iterations: 50,000
Analysis: Complex nested arrays and three 9-element (3x3) covariance matrices, still enqueued in nanoseconds. Serde handling of the nested structure adds no visible cost over a flat payload of the same size.
JointCommand (Multi-DOF Control)
Use Case: Manipulator joint control @ 500Hz
Size: 928 bytes (size_of; 1032 bytes declared)
send() median: 135 ns
send() p99: 226 ns
Sustained publish rate: 6.89M msg/s
Iterations: 50,000
Analysis: Kilobyte-scale command payloads enqueue in roughly the same time as the 304-byte Imu, so per-message overhead dominates the per-byte copy at this size.
LaserScan (2D Lidar Data)
Use Case: 2D lidar sensor data @ 10-40Hz Size: 1480 bytes
send() median: 210 ns
send() p99: 283 ns
Sustained publish rate: 4.42M msg/s
Iterations: 10,000
Analysis: At 1.5 KB the payload copy starts to show — the median is about 2.8x CmdVel's for 92x the bytes. This type runs 10,000 iterations, not 50,000 (benchmark_laserscan(iterations / 5)).
Comparison with traditional frameworks
Latency Comparison
Measurement Note: HORUS values below are send-only (one-direction). For round-trip (send+receive), approximately double them. The DDS rows are published reference values (64-byte messages, same-process, sourced to REP 2014 and the Eclipse iceoryx benchmarks) — they are not measured on this machine, and no benchmark in the repository produces them:
dds_comparison_benchmarkwas deleted for manufacturing competitor percentiles from two constants.
| Framework | Median | p99 |
|---|---|---|
| HORUS Topic (same process, 1:1) | 63 ns | 93 ns |
| HORUS Topic (cross process, 1:1) | 151 ns | 181 ns |
| iceoryx (C++) | ~80 ns | ~200 ns |
| CycloneDDS | ~1,500 ns | ~5,000 ns |
| FastDDS | ~2,000 ns | ~8,000 ns |
| ROS2 Default | ~5,000 ns | ~20,000 ns |
Performance Advantage: against the ROS2 default reference, HORUS is roughly 33x faster cross-process and 79x faster same-process; against FastDDS, roughly 13x and 32x.
Latency by Message Size
Measurement Note: The HORUS column is
send()enqueue cost measured byrobotics_messages_benchmarkwith an auto-selectedTopicbackend — no sample waits for delivery, so it is not even a full one-way latency. Sizes aresize_ofat runtime.The ROS 2 column divides that send-only figure by ROS 2's ~5 µs REP 2014 reference, which is an end-to-end number we did not measure. The two sides are therefore not like-for-like and the ratios are indicative, not a benchmark result. For a one-way-to-one-way comparison use the cross-process row above (151 ns), which gives roughly 33x.
| Message Size | Message Type | send() median | send() p99 | Sustained publish rate | vs ROS2 default (~5 μs) |
|---|---|---|---|---|---|
| 16 B | CmdVel | 75 ns | 135 ns | 12.14 M msg/s | ~67x faster |
| 304 B | Imu | 121 ns | 235 ns | 7.46 M msg/s | ~41x faster |
| 928 B | JointCommand | 135 ns | 226 ns | 6.89 M msg/s | ~37x faster |
| 1,480 B | LaserScan | 210 ns | 283 ns | 4.42 M msg/s | ~24x faster |
Observation: Enqueue cost grows far more slowly than message size — 92x more bytes costs under 3x — because the per-message overhead dominates the per-byte copy across this whole range.
Python Performance
The HORUS Python bindings (PyO3) call directly into the Rust shared memory layer, avoiding pickle serialization overhead. Python nodes and Rust nodes communicate through the same shared memory, enabling cross-language interoperability with minimal overhead.
Why Python HORUS is Fast:
- Zero-copy via Rust core: Python bindings call directly into Rust shared memory
- No pickle overhead: Messages use efficient binary serialization
- PyO3 efficiency: Minimal FFI overhead between Python and Rust
No published Python figures. Every number on this page comes from the Rust-side benchmarks; the repository publishes no reference latency or throughput figures for the Python bindings, so this section quotes none. To measure them on your own hardware run
python3 horus_py/benchmarks/bench_python.py(message round-trip, node tick overhead, zero-copy image conversion, multi-node scheduler throughput) orpython3 horus_py/benchmarks/research_bench_python.py --duration 30for sustained runs with a full p50/p95/p99/p99.9 distribution and CSV/JSON output.
TensorPool
HORUS TensorPool provides shared memory tensors optimized for ML/AI workloads. Pre-mapped shared memory means no malloc() on the hot path. Zeroing is not avoided, only moved: return_slot() scrubs a slot's data region before it returns to the free list, so the cost scales with tensor size (see the figures in TensorPool).
from horus import TensorPool
import numpy as np
# Create pool
pool = TensorPool(12345) # pool_id
# Allocate tensor (pre-mapped shared memory)
h = pool.alloc([1024, 1024], 'float32')
# Zero-copy NumPy view
arr = h.numpy() # No data copied
# Cross-process sharing via shared memory
descriptor = h.to_descriptor()
Key Advantages:
- Cross-process sharing via shared memory
- Pre-allocated pool — no malloc on hot path
- Refcounted handles — safe concurrent access
- Zero-copy NumPy —
.numpy()returns view
Running Rust Benchmarks
Quick Run
cd horus
cargo run --release -p horus_benchmarks --bin robotics_messages_benchmark
Available Benchmarks
| Binary | Description |
|---|---|
robotics_messages_benchmark | IPC latency with real robotics message types |
all_paths_latency | Topic latency across all backend routes (SpscShm, MpscShm, PodShm, raw-atomic floor) |
cross_process_benchmark | Cross-process shared memory IPC |
scalability_benchmark | Scaling with producer/consumer thread counts |
determinism_benchmark | Execution determinism and jitter |
topic_probe | One POD path, ~2s — the fast loop for hot-path work |
competitor_comparison | HORUS versus raw UDP loopback (single-thread; see the file header) |
iceoryx2_comparison | Comparison with iceoryx2 — requires --features iceoryx2 |
Run any benchmark with:
cargo run --release -p horus_benchmarks --bin <name>
# JSON output for CI/regression tracking. Accepted by all_paths_latency,
# cross_process_benchmark, determinism_benchmark, robotics_messages_benchmark
# and scalability_benchmark only.
cargo run --release -p horus_benchmarks --bin <name> -- --json results.json
# competitor_comparison writes CSV instead
cargo run --release -p horus_benchmarks --bin competitor_comparison -- --csv comparison.csv
# topic_probe prints per-repetition lines instead
cargo run --release -p horus_benchmarks --bin topic_probe -- --raw
topic_probe, competitor_comparison and iceoryx2_comparison do not parse --json: the first
two scan the command line only for their own flags, and iceoryx2_comparison never reads it at
all. Passing -- --json results.json to one of them produces an ordinary run, no error and no
file, so a CI step that collects the file has to check that it exists.
Criterion micro-benchmarks:
cd horus
cargo bench -p horus_benchmarks
Expected Output
╔══════════════════════════════════════════════════════════════════╗
║ HORUS Robotics Message Types Benchmark ║
╠══════════════════════════════════════════════════════════════════╣
║ Testing real-world robotics message latency (REP 2014) ║
╚══════════════════════════════════════════════════════════════════╝
Platform: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz (12 cores)
Iterations: 50000
Warmup: 5000
╔═════════════════════════════════════════════════════════════════════════════╗
║ Message Type │ Size (bytes) │ Typical Rate │ Use Case ║
╠═════════════════════════════════════════════════════════════════════════════╣
║ CmdVel │ 16 │ 1000+ Hz │ Velocity control commands ║
║ Imu │ 296 │ 500+ Hz │ IMU sensor fusion ║
║ LaserScan │ 1480 │ 10-40 Hz │ 2D lidar navigation ║
║ JointCommand │ 1032 │ 500+ Hz │ Manipulator control ║
╚═════════════════════════════════════════════════════════════════════════════╝
[Topic] Running benchmarks — timing tx.send() enqueue cost only
(cross-thread consumer drains in the background; no sample
waits for delivery, so these are NOT end-to-end latencies)
─────────────────────────────────────────────────
CmdVel 16 bytes │ median: 75ns │ p99: 135ns │ CV: 1.3146
Imu 304 bytes │ median: 121ns │ p99: 235ns │ CV: 1.1833
LaserScan 1480 bytes │ median: 210ns │ p99: 283ns │ CV: 0.6795
JointCommand 928 bytes │ median: 135ns │ p99: 226ns │ CV: 0.8705
The run also prints a SUMMARY BY MESSAGE TYPE table with throughput and a REAL-TIME SUITABILITY ANALYSIS block. The sizes in the banner table (296 B for Imu, 1032 B for JointCommand) are hard-coded labels in the benchmark header; the per-type result lines print the real std::mem::size_of values (304 B and 928 B).
Use Case Selection
Message Type Guidelines
CmdVel — 16 B, 75 ns median / 135 ns p99
- Motor control @ 1000Hz
- Real-time actuation commands
- Safety-critical control loops
Imu — 304 B, 121 ns median / 235 ns p99
- High-frequency sensor fusion @ 500Hz
- State estimation pipelines
- Orientation tracking
JointCommand — 928 B, 135 ns median / 226 ns p99
- Multi-DOF manipulator control @ 500Hz
- Coordinated joint trajectories
- Arm and gripper command streams
LaserScan — 1480 B, 210 ns median / 283 ns p99
- 2D lidar @ 10-40Hz
- Obstacle detection
- SLAM front-end
Performance Characteristics
Strengths
- Sub-microsecond latency for messages up to 1.5KB
- Consistent performance across message types (low variance)
- Graceful scaling with message size
- Production-ready throughput with large headroom
- Serde integration handles complex nested structs efficiently
Additional Notes
- Complex structs (Imu with three 9-element covariance matrices): 121 ns median — still sub-microsecond
- Large messages (LaserScan at 1480 B): 210 ns median — a 92x size increase over CmdVel costs under 3x latency
Real-World Applications
| Application | Message | Frequency | HORUS median | ROS2 default (REP 2014 ref) | Speedup |
|---|---|---|---|---|---|
| Motor control | CmdVel (16 B) | 1000 Hz | 75 ns | ~5 μs | ~67x |
| Sensor fusion | Imu (304 B) | 500 Hz | 121 ns | ~5 μs | ~41x |
| Manipulator control | JointCommand (928 B) | 500 Hz | 135 ns | ~5 μs | ~37x |
| Lidar SLAM | LaserScan (1480 B) | 10-40 Hz | 210 ns | ~5 μs | ~24x |
Methodology
Benchmark Pattern: Send-Side and One-Way
HORUS measures latency in one direction only — no acknowledgement leg is sent:
Why one-way?
- Comparable: matches the one-way figures published by REP 2014 and the iceoryx benchmarks
- No return-path bias: a round-trip number blends two directions plus the consumer's wake-up cost
- Cross-core: producer and consumer are pinned to separate physical cores, so cache-coherency cost is included
- Conservative for cross-process: the timestamp is written before
send()and read afterrecv(), so serialization, IPC and deserialization are all inside the measurement
What we measure:
- send — producer-side
send()latency via RDTSC. The subtracted overhead is the minimum of 10,000 back-to-backrdtsc()/rdtscp()pairs with no work between them, calibrated once per process (same-process scenarios) - one-way — producer → consumer latency from an RDTSC timestamp carried in
CmdVel.timestamp_ns(cross-process scenarios) - broadcast — one-way latency on latest-value PodShm paths, plus read freshness and skip-ahead counts
What we DON'T measure:
- Round-trip as the headline number. The offset-free cross-process scenario
(
Topic_cross_process_oneway_pingpong) does send a reply — that is how it cancels the two cores' TSC offset, NTP-style — but it reports(fwd + rev) / 2, a one-way figure.rtt / 2is printed beside it, labelled as a halved round trip, and is the larger of the two because it also carries the responder's recv→send turnaround. - Burst throughput (no backpressure)
- Same-core communication (unrealistic for multi-process IPC)
Test Environment
- Build:
cargo build --releasewith full optimizations - CPU Governor:
performancemode recommended; the figures quoted on this page were captured underpowersave, which inflates cross-process latencies - CPU Affinity: Producer and consumer pinned to separate physical cores (
all_paths_latencyreadsthread_siblings_listto pick five distinct physical cores, falling back to 0/2/4/6/8 only when the kernel will not report topology) - Process Isolation: Dedicated topics per benchmark
- Warmup: 5,000 iterations discarded before measurement (10,000 for
determinism_benchmark; 1,000 for the LaserScan case inrobotics_messages_benchmark) - Measurement: RDTSC (cycle-accurate timestamps)
Message Realism
- Actual HORUS library message types
- Serde serialization (production path)
- Realistic field values and sizes
- Complex nested structures (Imu, LaserScan, JointCommand)
Statistical Methodology
- 50,000 iterations per message type (
robotics_messages_benchmark, override with--iterations) — except LaserScan, which is called withiterations / 5, so 10,000 by default; 100,000 samples per scenario (all_paths_latency,determinism_benchmark) - Median, p95, p99, p99.9 latency tracking
- Tukey IQR outlier counting (1.5x fence), reported as a diagnostic only — every published statistic is computed from the full, unfiltered sample set, because the fence deletes exactly the preemptions and page faults that constitute the tail
- Bootstrap 95% confidence intervals (10K resamples), also over the full sample set
- Variance tracking (min/max ranges, coefficient of variation)
- Multiple message sizes
Measurement Details
RDTSC Calibration:
- Null cost (back-to-back rdtsc): ~36 cycles
- Target on modern x86_64: 20-30 cycles
- Timestamp embedded directly in message payload
Cross-Core Testing:
- Producer and consumer on different CPU cores
- Simulates real multi-process robotics systems
- Includes cache coherency overhead (~60 cycles theoretical minimum)
Scheduler Performance
Scheduler Features
Key capabilities:
- Execution classes:
.compute()moves long-running nodes off the tick path,.async_io()for blocking I/O,.rate()and.order()for per-node pacing and ordering - Fault Tolerance: per-node
FailurePolicy—Fatal,Restart { max_restarts, initial_backoff },Skip { max_failures, cooldown },Ignore - Deterministic mode: opt-in sequential execution with reproducible runs —
Scheduler::new().deterministic(true)(default isfalse) - Safety Monitoring: tick budgets, deadline-miss policies (
Miss), watchdogs and a blackbox recorder
Scalability Performance
The Criterion bench scheduler_ipc_latency sweeps node counts 0/1/5/10/20 and topic counts 0/1/5/10. Larger node and topic counts are not benchmarked in this repository.
Topic scaling (send + recv latency, Intel Core i7-10750H, powersave governor):
| Topics | p50 | p99 |
|---|---|---|
| 1 | 66 ns | 80 ns |
| 10 | 65 ns | 88 ns |
Only the counts the bench actually sweeps are listed. bench_latency_by_topic_count
iterates [0, 1, 5, 10], so rows for 50, 100, 500 and 1,000 topics would be numbers
nobody measured — they were on this page, and they are gone.
Key Insights:
- Topic lookup does not degrade across the range that is measured (1 to 10 topics). Whether it stays flat at 1,000 is untested here; measure it if you depend on it
- The repository README reports near-linear scheduler scaling to 100 nodes (~14% degradation) and O(1) topic lookup to 1,000 topics, without attributing either to a machine. No benchmark in the repository produces either figure — the largest sweeps are 20 nodes and 10 topics — so treat both as unsourced until they are regenerated
- Node-scaling timings are dominated by OS scheduling noise under the
powersavegovernor and vary substantially run-to-run; measure on your own hardware with theperformancegovernor before quoting numbers
cargo bench -p horus_benchmarks --bench scheduler_ipc_latency
Real-Time Performance
Real-Time Node Configuration
HORUS provides real-time facilities for applications with explicit timing constraints:
RT Features:
- Tick budget enforcement:
.budget(Duration)per node, reporting aBudgetViolationwhen a tick overruns - Deadline handling:
.deadline(Duration)with.on_miss(Miss::Warn | Miss::Skip | Miss::SafeMode | Miss::Stop), plusScheduler::max_deadline_misses() - Failure policies: per-node
FailurePolicy::Fatal,Restart { max_restarts, initial_backoff },Skip { max_failures, cooldown },Ignore - Watchdog Timers:
.watchdog(Duration)on the scheduler or on individual nodes, to detect hung or crashed nodes
Full Safety-Monitoring Configuration
Running with full safety monitoring enabled:
use horus::prelude::*;
let mut scheduler = Scheduler::new()
.tick_rate(1000_u64.hz())
.prefer_rt()
.watchdog(10_u64.ms())
.max_deadline_misses(100);
scheduler
.add(motor_controller)
.order(0)
.rate(1000_u64.hz())
.budget(200_u64.us())
.on_miss(Miss::SafeMode)
.failure_policy(FailurePolicy::Fatal)
.build()?;
No published overhead figures. The repository contains no benchmark that measures watchdog resolution, emergency-stop time, deadline-detection jitter or budget-tracking overhead, so this page does not quote any. For scheduler timing behaviour run
cargo bench -p horus_benchmarks --bench scheduler_jitter, which measures RT tick interval jitter at 500 Hz with and without competing compute nodes.
All-Routes Latency
HORUS automatically selects the backend from the producer/consumer counts and whether the message type is POD. Every topic is shared-memory backed, so the same-thread, cross-thread and cross-process scenarios below can resolve to the same backend — what changes between them is where the two ends run, not the transport. This benchmark measures the latency of each automatically-selected route.
Benchmark Results
Measured with all_paths_latency on an Intel Core i7-10750H (6C/12T, powersave governor), 100K samples per scenario, RDTSC timing with calibrated overhead subtraction. The benchmark defines no target values — these are the scenario names and columns it actually reports.
| Scenario | Type | Backend | p50 | p99 |
|---|---|---|---|---|
| SameThread | send | SpscShm | 20 ns | 26 ns |
| CrossThread-1P1C | send | SpscShm | 63 ns | 93 ns |
| CrossThread-MP1C | send | MpscShm | 226 ns | 429 ns |
| CrossThread-1PMC | send | PodShm | 74 ns | 120 ns |
| CrossThread-MPMC | send | PodShm | 190 ns | 354 ns |
| CrossProc-1P1C | one-way | SpscShm | 151 ns | 181 ns |
| CrossProc-2P1C | one-way | MpscShm | 279 ns | 374 ns |
| CrossProc-1PMC | one-way | PodShm | 191 ns | 209 ns |
| CrossProc-PodShm | broadcast | PodShm | 223 ns | 270 ns |
| RawAtomic (hardware floor) | one-way | raw shm | 79 ns | 102 ns |
MP1C/MPMC scenarios are contended (2 producers, or 2 producers and 2 consumers). Framework overhead is the gap to the RawAtomic floor — 72 ns for cross-process 1:1.
Key Achievements
- 20 ns same-thread and 63 ns cross-thread for uncontended 1:1 paths
- ~200 ns for contended multi-producer same-process paths (226 ns MP1C, 190 ns MPMC)
- Sub-200ns for cross-process 1:1 (151 ns)
- ~280 ns for multi-producer cross-process (2 producers → 1 consumer)
- Zero configuration — optimal path selected automatically
- Seamless migration — path upgrades transparently as topology changes
Running the Benchmark
cd horus
cargo build --release -p horus_benchmarks
./target/release/all_paths_latency
Summary
HORUS provides production-grade performance for real robotics applications:
Automatic Path Selection (all_paths_latency, p50):
- 20 ns — Same-thread (SpscShm)
- 63 ns — Cross-thread, 1:1 (SpscShm)
- 151 ns — Cross-process, 1:1 (SpscShm)
- 279 ns — Cross-process, 2 producers → 1 consumer (MpscShm)
- 223 ns — Cross-process broadcast, N:N (PodShm)
- 79 ns — Raw shared-memory atomic (hardware floor)
Robotics Message Types (robotics_messages_benchmark, median):
- 75 ns — CmdVel, 16 B (motor control)
- 121 ns — Imu, 304 B (sensor fusion)
- 135 ns — JointCommand, 928 B (manipulator control)
- 210 ns — LaserScan, 1480 B (2D lidar)
Ready for production deployment in demanding robotics applications requiring real-time performance with complex data types.
Next Steps
- Learn how to maximize performance: Performance Optimization
- Explore message types: Message Types
- See usage examples: Examples
- Get started: Quick Start
Build faster. Debug easier. Deploy with confidence.