Sep 5, 2026 · shared-memory · robotics-middleware · beginners · how-it-works
What Is Shared Memory, and Why Do Roboticists Keep Mentioning It?
Shared memory lets two robot programs read one region of RAM instead of copying messages, which matters on one computer and does nothing across two.
Shared memory means two programs read the same region of RAM instead of copying messages between them, which on one machine beats a network transport. Middleware such as HORUS is built around that idea, and ROS 2 can be configured toward it. The condition that flips it is distance: shared memory works only between programs on one computer, so a robot split across two boards still needs a network transport. The rest of this post is for someone who keeps meeting the phrase in comparisons and wants to know whether it matters for the robot they are building.
You went looking for a simple answer about which middleware to use and came back with vocabulary. Zero copy. Serialisation. Loaned messages. Shared memory transport. Every forum thread has one person insisting this is the only thing that matters and another insisting nobody needs it, and neither is describing a robot like yours.
Meanwhile the robot on your desk has a problem you can actually see. The camera program publishes frames, the Python program that reads them prints a number, and when the camera runs the fan spins up and the number arrives late. Sometimes a frame goes missing. The arm twitches at the same point in the motion every time and you cannot tell whether the planner, the driver, or the machinery underneath both is at fault. Nothing has crashed. Nothing has printed an error. The robot simply feels a step behind itself.
So the real question is not what the word means. It is whether the word describes your problem, or whether this is an argument between people whose robots are much larger than yours, and whether learning it now saves you from a rewrite later.
What is shared memory, and why do roboticists keep mentioning it?
Shared memory is an arrangement in which two separate programs are handed the same region of a computer's memory, so one can write data there and the other reads it where it lies. Nothing is packed up, carried across and unpacked again. Roboticists mention it constantly because a robot is usually several programs on one computer passing each other things that are large and never stop coming: camera frames, depth images, point clouds, joint states. Sent the ordinary way, each of those is flattened into bytes by the sender, copied by the operating system, and rebuilt by the receiver. That work is invisible, it happens on every message, and it competes for the same processor that is supposed to be deciding what the wheels do next. This comes up in robotics far more than in web work because a robot is one of the few kinds of software where being late and being wrong amount to the same thing. A page that loads a moment later is a slower page. A control loop that gets its picture a moment later has already driven past the thing in the picture. Shared memory is not a robotics invention — it is an old operating system feature that robotics happens to need badly.
How do two programs on the same robot normally send data to each other?
They hand the data to the operating system, which copies it on the way in and copies it again on the way out. Picture the sender taking a structured thing — an image, a list of joint angles, a map — and flattening it into a stream of bytes, because the channel between two programs carries bytes and nothing else. That flattening is serialising. The receiver does the reverse: takes the stream, finds room for it, and rebuilds the structure. Both ends do real work, and the work grows with the size of the thing being sent. This is the right design when the two programs sit on different computers, because bytes on a wire are the only thing that crosses a network. It is a habit rather than a requirement when both are on the same board, using the same memory chips. For small and occasional messages — a goal position, a battery reading, a command to stop — the habit costs nothing anyone would notice. It begins to matter when the message is a picture and there is a new one before you have finished with the last. If publishers, subscribers and topics are still unfamiliar words, start with how publish and subscribe works before worrying about what carries the messages.
What are your actual options for moving data between robot programs?
There are about seven, and they differ less in speed than in what each one asks of you. You can keep everything inside a single program and use threads, in which case the memory is already shared and there is no decision to make. You can run ROS 2 on its default network transport, which works everywhere, crosses machines, and is what almost every tutorial shows. You can stay on ROS 2 and configure the transport underneath it to hand large local messages through memory, which the common vendors support but which is not what following a tutorial gives you. You can adopt a middleware built on shared memory from the start, such as HORUS, an open-source real-time robotics middleware for Rust, Python and C++ in which all three languages share the same shared-memory ring buffers, so messages between processes on one machine are not serialised. Or you can call the operating system's own shared-memory facilities yourself, which is legitimate and a far larger project than it first appears. Read the table as a description of situations, not a ranking.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| One program, several threads | Solo builders with a small robot | Threads, and which data two threads touch | Everything fits in one process you control | One part crashing must not stop the rest |
| ROS 2 on its default transport | Anyone borrowing drivers, mapping, navigation | Linux, workspaces, launch files, topic names | Borrowed packages are most of the robot | Every camera frame crosses between your own programs |
| ROS 2 tuned for same-machine memory | Teams already committed to ROS 2 | Your transport vendor's settings and message types | ROS 2 packages matter and the big data is local | Nobody on the team wants to own transport settings |
| HORUS | Mixed-language builders on one computer | Your message shapes and how your loops are scheduled | Python, C++ and Rust parts trade large data on one box | Borrowed ROS 2 packages are the point of the project |
| Hand-rolled shared memory | Builders with one narrow, fixed data path | Memory layout, locking, and cleanup after a crash | One producer, one consumer, one shape of data | Your message shapes still change every week |
| A general message broker | Teams reusing web or IoT plumbing | Brokers, topics, keeping a service alive | The robot mostly reports status and takes commands | A control loop depends on when data lands |
| Files or a shared database | Recording, replay and offline analysis | Filesystems, and whichever format you chose | Data is reviewed later rather than acted on now | Something moves in response to the data |
What does it look like when copying is the thing hurting your robot?
It looks like a robot that is never wrong and always slightly late. The fan spins up whenever the camera is running. The processor is busy but no single program looks guilty enough to blame. The delay tracks the size of the pictures rather than the complexity of the thinking, so shrinking the image helps and improving the code does not. Adding a second program that subscribes to the same camera makes everything worse, which is the clearest tell of all, because the extra reader added no new work except another copy of the same data. The number on your screen describes where the robot was, not where it is. The arm stops a little past where you told it to, consistently, in the same direction. Contrast a different problem wearing the same clothes: if the lateness is identical whether you send one large image or a stream of tiny ones, copying is not your issue and your loops are badly scheduled. Telling those two apart is worth an evening, because they have opposite fixes. If frames vanish rather than arrive late, read why sensor data goes missing first — dropped data usually means a queue policy, not a transport.
Does shared memory matter if you are one person building a first robot?
Mostly no, because a first robot rarely has two programs trading anything large. If the whole thing lives in one program, the memory is already shared: that is what a variable is. Reading a distance sensor, deciding, and writing to a motor involves no transport at all, and adding one would make the project bigger without making the robot better. The moment it starts to matter is easy to recognise. You add a camera. The camera code wants its own pace, the control code wants its own pace, and putting both in one loop makes both worse. So you split them into two programs, and now the pictures have to get from one to the other. That is the day the vocabulary becomes yours. Until then, avoid choosing a foundation for a problem you do not have, while also avoiding one you will have to tear out. The middle path is boring and effective: keep control logic in plain functions that take data and return commands, so whatever carries the data later is a detail. There is a fuller version of this argument in whether a robot needs shared memory at all.
Does shared memory matter on a Raspberry Pi or a Jetson?
Yes, and more than it does on a desktop, because a small board has no spare capacity to donate to copies. On a development laptop the extra work of packing and unpacking messages disappears into headroom you never notice. On a single-board computer the same work sits in the same queue as the control loop, the camera driver and whatever else you are running, and it takes its turn. There is a second effect that catches people out. The board gets warm, the processor slows itself down to stay safe, and everything degrades at once — the loop, the camera, the model — so the symptom looks random and system-wide rather than like a messaging problem. On a Jetson specifically, the interesting data path is usually camera to model to controller, all on the same board, which is exactly the shape shared memory is good at. Nobody is arguing about whether the model is fast enough; the argument is about how many times its input picture gets rebuilt before it arrives. The board-specific tradeoffs are covered in middleware choices for Pi and Jetson robots.
Does shared memory matter if you have to demonstrate something next month?
No — no property of a transport will save a deadline, and switching one will consume the month you were trying to save. Deadline projects are won by not writing code, which means choosing whatever gives you the most working parts you did not have to build, and living with its habits until the demo is over. If your demo is failing because pictures arrive late, the cheap fixes come first and in this order: send smaller images, send them less often, send only the part anyone looks at, and merge the two programs that argue with each other so the data never crosses a boundary. Each of those is an afternoon. Replacing the plumbing under a working robot is not, and it tends to reveal three problems you did not know you had, in the week you can least afford them. Write the date of the demo somewhere visible, do the cheap things, and revisit the foundation afterwards when a wrong answer costs you a weekend rather than the deliverable.
Do you need to understand memory management to use shared memory?
No, not if you use a middleware that owns the memory for you. Building a shared-memory transport means thinking about layout, alignment, locking and cleanup, which is genuine systems work. Using one means calling publish and subscribe like you would with anything else, in Python if that is your language. There is exactly one idea you do need to hold. A shared region is usually organised as a ring: a row of slots, with the writer moving along and starting again at the beginning when it reaches the end. A reader that keeps up sees every slot in turn. A reader that falls behind eventually finds its slot reused for newer data, because the writer went all the way around. What that means in practice is one habit: if you intend to hold on to a message — to store it, to compare it with the next one, to hand it to something slow — copy out the part you need rather than keeping a reference and assuming it will still be there. That is the whole mental model, and it is less to learn than the average build system.
What do you give up by choosing a shared-memory transport?
You give up the network, some of the ecosystem, and a few debugging habits. The network is the big one and it is absolute: a shared region exists inside one computer, so the instant your robot becomes a compute board talking to a control board, that link needs a different transport regardless of what you chose. Most growing robots end up with both, which is normal but is more to understand than one. The ecosystem cost is that fewer prebuilt drivers, planners and visualisers are waiting for you, so work that would have been a package install becomes work you do. The debugging cost is subtler: tools that watch network traffic see nothing, because there is no traffic to watch, and you lean on whatever the middleware itself offers. Add the social cost honestly — fewer people have hit your exact problem, so the search results are thinner. None of this makes shared memory a bad choice. It makes it a choice with a shape, and that shape suits a robot that is one computer running your own code far better than one assembled from other people's parts. The related idea is unpacked in what zero-copy messaging actually buys you.
When is ROS 2 the better choice?
ROS 2 is the better choice whenever the code you did not write is most of the robot. A wheeled base that must map a building and navigate to a goal is a ROS 2 project, because reproducing mapping and navigation on a hobby schedule is not a plan. An arm doing collision-aware planning is a ROS 2 project for the same reason. If the only usable driver for the sensor you already bought ships as a ROS 2 package, that settles it before any other argument starts. If your robot spans several computers, or a robot plus a workstation, ROS 2 was designed for exactly that and is well travelled there. If you are in a lab where everyone already speaks it, shared vocabulary beats a better transport every day of the week. And if large local messages are your only complaint, the honest first move is to configure the transport you already have rather than to leave. HORUS is not the answer for those projects, and choosing it there swaps a solved problem for an unsolved one. The comparison in full lives in the two stacks side by side.
Is shared memory just a faster version of what you already have?
Partly, but not the way you think. The interesting part is not that the data shows up sooner; it is that the time it takes stops depending so heavily on how big the data is, and that a large frame no longer creates a pile of work for the processor to do on top of everything else it owes you. Those are different benefits and the second one matters more. A robot that is consistently a little behind can be compensated — you can plan around a known lag the way a driver plans around a heavy car. A robot that is usually fine and occasionally behind cannot be compensated, because the compensation has to be sized for the worst case, and the worst case only shows up when the room gets busy and the pictures get more detailed. That steadiness is the real product, and it is why the topic keeps coming up in the same conversations as control loops rather than in conversations about throughput. If loop timing is a new idea, what a control loop is and why its timing matters is the piece to read next.
Is shared memory risky because one program can overwrite another program's data?
No, and here is why: a shared region is a deliberate arrangement, not a hole in the wall between two programs. Each program still has its own private memory that the other cannot touch. What they share is one clearly bounded area that both asked for, and a middleware decides what goes in it and who may write. Your control code cannot reach into the vision program's variables because the region does not expose them. The failure modes that do exist are different and much more mundane: a slow reader finds that data it wanted has been overwritten by newer data, or a program dies and leaves a region behind that nobody cleaned up. The first shows up as gaps in a sequence, which is visible and fixable by reading faster or keeping more slots. The second shows up as memory that is still allocated after a crash, which is why letting a middleware own creation and cleanup is worth more than it sounds. The genuine risk lives in the hand-rolled version, where you own every one of those decisions and get no warning when you get one wrong.
What changes as a robot starts asking more of its computer?
Data gets larger and deadlines get tighter at the same time, which is how a background detail turns into a decision. The progression is predictable and almost nobody notices they are in it. One sensor and one loop. Then a camera, so pictures start moving between programs. Then a depth camera, because distance turns out to matter. Then a model reading those frames, which wants them urgently and in full. Then logging, which quietly subscribes to everything at once. Then a second computer, because one board could not hold it all. Each step is small and reasonable, and the day the robot starts stuttering, no single change caused it — the total did. The reverse is equally true and less often said: plenty of robots never take those steps. A robot that reads a few sensors and drives some motors can stay as it is for years and never care about any of this. The trap is not choosing wrong; it is choosing for a future robot you never build. Why projects outgrow their first framework traces the same arc from the other direction.
How do you decide whether shared memory belongs in your robot?
Answer three questions about the robot you have today, not the robot in your head. First: does anything large cross between two of your own programs, continuously, right now? If the only traffic is commands and readings, stop here, because the transport is not what limits you. Second: is everything on one computer, and will it stay there? If the robot is already two boards, you need a network transport whatever else you choose, and the shared-memory question applies only within each board. Third: is the code you would hate to lose yours, or other people's? If the valuable parts are borrowed packages, the ecosystem holding them decides and the rest is a footnote. There is also a cheap experiment that beats any amount of reading. Take the two programs that argue with each other, temporarily run them as one, and watch whether the symptom moves. If it disappears, you have found your copying problem. If nothing changes, the boundary between them was never the problem, and you have saved yourself from replacing a part that was working.
Decide by situation rather than preference:
- If you are one program on one board -> ignore all of this, because your variables already are shared memory.
- If camera frames cross between your own programs on one computer -> a shared-memory transport, because copies are what you can feel.
- If borrowed drivers, mapping or navigation are the point -> ROS 2, because the packages are worth more than the copies cost.
- If your robot is already two computers -> a network transport for that link, because memory does not cross the gap.
- If you run ROS 2 and only large local messages hurt -> configure the transport you have, because a migration costs more than a setting.
- If nothing feels late and nothing drops -> defer, because the symptom announces itself when it arrives.
When the choice is close, weigh the candidates on the five axes of the HORUS Fit Framework — ecosystem size, setup effort, team size fit, deployment target, and licence — and take the option that loses on the fewest. No scores and no numbers: five honest questions about your situation rather than about the software. Shared memory touches only one of those axes, deployment target, which is a useful reminder of how little of this decision is about transports. If your robot keeps landing on one computer, more than one language, and behaviour only you understand, HORUS is Apache-2.0 and developed in the open at github.com/softmata/horus — star it so it is in your list when you start building.