I am currently developing a simple controller. It consists of a GUI
(C++) and a controller (ruby) that talks to a serial port.
Now, I understand that this can (or maybe should) be combined into a
single app that communicated directly with the serial port. However,
I wouldn't have the opportunity to ask this question if that were the
case!
So, I have an embedded ARM proc with about 200MHz, and I want this app
to feel as responsive as possible. The GUI and controller will both
run on this machine. When a button on the GUI is pressed, the command
is sent to the controller, the controller sends a command out of the
serial port, and an action is taken.
Let's assume that all parts not including the IPC between the GUI and
the controller are working fine. My question deals with the local IPC
between the GUI and the controller.
I really like XML/RPC. It is really easy and straightforward in Ruby,
and has worked really well in the past for network-based distributable
apps. However, in this case I can see how the overhead of XML and
"IP" communication might make the app feel too slow (It would be bound
to localhost, of course).
I would really like to use a standard protocol, preferably one
natively implemented in ruby already. I just need it to be fast...
So, with all of that info, what does the community recommend for a
lightening fast interprocess communication method?
Feel free to tell me that XML/RPC is fast enough, if it is...
How responsive are we talking about here? Do you need "twitch" video game type responsiveness (tens of ms) or something less? Unless you need twitch video game responsiveness, I'm pretty sure anything over the local loopback would be fast enough. I've written CGIs that ran on the webserver of an ARM-based embedded device, and despite the overhead of a *real* network between me and them, they seemed very responsive.
If you need tens-of-ms type responsiveness, you might want to use some shared memory. This couldn't be done natively in Ruby, but it would be pretty easy to write some simple C, write a Ruby extension, and use it that way.
Keep in mind that in my experience, you'll never be able to get any better than say 20ms responsiveness, since that's the task-switching overhead inherent in using Linux (and I assume other OSes would be similar). You *could* get faster by writing kernel extensions, but that's even further from a pure Ruby implementation.
Ben
···
On Jan 17, 2007, at 17:30, James Mills wrote:
So, I have an embedded ARM proc with about 200MHz, and I want this app
to feel as responsive as possible. The GUI and controller will both
run on this machine. When a button on the GUI is pressed, the command
is sent to the controller, the controller sends a command out of the
serial port, and an action is taken.
So, with all of that info, what does the community recommend for a
lightening fast interprocess communication method?
Depending on the size of your messages, why not use UDP and your own simple message format? You'd eliminate the overhead of TCP, not to mention the bloat of XML. You could send the data for the serial port with a header or Ruby code prepended, then interpret the header or eval the code...
I am currently developing a simple controller. It consists of a GUI
(C++) and a controller (ruby) that talks to a serial port.
Now, I understand that this can (or maybe should) be combined into a
single app that communicated directly with the serial port. However,
I wouldn't have the opportunity to ask this question if that were the
case!
So, I have an embedded ARM proc with about 200MHz, and I want this app
to feel as responsive as possible. The GUI and controller will both
run on this machine. When a button on the GUI is pressed, the command
is sent to the controller, the controller sends a command out of the
serial port, and an action is taken.
Let's assume that all parts not including the IPC between the GUI and
the controller are working fine. My question deals with the local IPC
between the GUI and the controller.
I really like XML/RPC. It is really easy and straightforward in Ruby,
and has worked really well in the past for network-based distributable
apps. However, in this case I can see how the overhead of XML and
"IP" communication might make the app feel too slow (It would be bound
to localhost, of course).
I would really like to use a standard protocol, preferably one
natively implemented in ruby already. I just need it to be fast...
So, with all of that info, what does the community recommend for a
lightening fast interprocess communication method?
Feel free to tell me that XML/RPC is fast enough, if it is...
Be lazy! Write a XML/RPC version (if you think it's not a lot of work), and only think about more "complicated" IPC if it's not enough. You can always blame Ben Giddings or me! =P
Paulo Jorge Duarte Köch
paulo.koch@gmail.com
···
On 2007/01/17, at 23:06, Ben Giddings wrote:
On Jan 17, 2007, at 17:30, James Mills wrote:
So, I have an embedded ARM proc with about 200MHz, and I want this app to feel as responsive as possible.
I've written CGIs that ran on the webserver of an ARM-based embedded device, and despite the overhead of a *real* network between me and them, they seemed very responsive.
The TCP overhead is there for a purpose. UDP is an unreliable protocol. Packets may get dropped, duplicated, or reordered. If your application is OK with that, great, but if not then you are going spend a lot of time designing what basically amounts to TCP (sequence numbers, retransmission strategies, and so on).
Gary Wright (Radar)
···
On Jan 18, 2007, at 12:06 AM, ian dacek wrote:
James Mills wrote:
So, with all of that info, what does the community recommend for a
lightening fast interprocess communication method?
Depending on the size of your messages, why not use UDP and your own simple message format? You'd eliminate the overhead of TCP, not to mention the bloat of XML. You could send the data for the serial port with a header or Ruby code prepended, then interpret the header or eval the code...
So, with all of that info, what does the community recommend for a
lightening fast interprocess communication method?
Depending on the size of your messages, why not use UDP and your own simple message format? You'd eliminate the overhead of TCP, not to mention the bloat of XML. You could send the data for the serial port with a header or Ruby code prepended, then interpret the header or eval the code...
The TCP overhead is there for a purpose. UDP is an unreliable protocol. Packets may get dropped, duplicated, or reordered. If your application is OK with that, great, but if not then you are going spend a lot of time designing what basically amounts to TCP (sequence numbers, retransmission strategies, and so on).
That's generally true of UDP, especially between two remote hosts bridged by a router.
However, going between two ports on the localhost should actually net something along the lines of a memory copy, depending on the behind-the-scenes networking implementation.
Memory allocation/starvation issues can cause lost UDP packets even to/from a single host. I'll bet there are other possibilities. It is just a bad starting point to make the assumption that it will be reliable in your particular circumstance. Of course there are circumstance in which in will work anyway.
If you know it is to/from the same host then Unix domain sockets might be an option.
In any case, I just wanted everyone reading that thread to be aware of the caveats of UDP-based protocols.
Gary Wright
···
On Jan 18, 2007, at 8:14 PM, ian dacek wrote:
That's generally true of UDP, especially between two remote hosts bridged by a router.
Thanks to everyone who had ideas on this one. I love mailing lists.
I ended up using popen3 to launch the GUI from within the ruby code.
I created a listening thread on the stdout handle, and acted upon
anything that came in. This has several advantages for this project.
* The GUI is really dumb. All it does is generate a three-letter
message to stdout when a button is pressed or released.
* All of the prep code and routines needed to set up the serial port
comms and other prop data can be done before the GUI is launched.
* The GUI could be tested independently from the ruby portion. This
was good since it was developed remotely.
In this scenario, popen3 was perfect! It was really fast, and it is built in.