Is asynchronous IPC preventing us from using parallelism?
Posted: Sat Jun 02, 2012 3:57 am
Let's take an example first, we want to read from two files at the same time assuming the HW and underlying SW can handle it. In the case you have synchronous IPC you create two threads, open files, read them using synchronous IPC and the exit the thread when it has been done. In the case we have asynchronous IPS we have the possibility to do this in one thread, we can open and start read requests in the same thread. Here we must a have some kind of message loop and also we must have some mechanism to distinguish which message belongs to which file. Of course with asynchronous IPC starting two threads is possible as well however asynchronous IPC often do mind tricks with us so that we get trap in the serialization way of thinking not exploiting the possibility of starting new threads. With only synchronous IPC we would have to start new threads.
Another example, we send data to some kind of interface, it is slow like RS232 for example. Here we have use of the benefits of asynchronous IPC, serialization and non blocking send. However, since the interface is slow we can send much faster than the interface can send on its end. Now we have two possibilities, to discard data or stall until the interface is ready to accept more data. I think most of the time we don't want to lose any data so we must wait. In practice on the interface driver end, you probably have implemented this with two threads if we only have synchronous IPC. One sending thread and one thread accepting data which puts the data in a buffer. Using two threads gives us almost non blocking send (still we have task switch but the blocking is short). When the buffer is full, the buffer thread simply don't go into receive state preventing the rendevouz. Now we have implemented flow control in simple way. This is of course possible with asynchronous IPC as well, either by waiting for a reply from the interface thread or having some kind of blocking mechanism in the kernel when the message pool is full. Blocking when the message pool is full is much less trivial than the rendevouz block.
So in practice asynchronous IPC doesn't help us in that much in real scenarios and might rather discourage us from using the parallelism provided by modern CPUs. You often fall into the trap of serialization using asynchronous IPC. Also asynchronous IPC require more involvement from the kernel when in comes to message pool management and states it must support. The benefit of asynchronous IPC is less task switching but as you could see with the second example, we often don't get rid of it anyway.
Having asynchronous IPC adds to the complexity a lot and also we have to support more different scenarios that can happen with asynchronous IPC, the complexity just increases for very little benefit. My kernel supports both asynchronous and synchronous IPC but I'm starting to wonder if supporting asynchronous IPC is really worth the effort. It requires much more code and involvement from the kernel and adding security to it just makes even more complex. Mach kernel is a good example of this where the IPC was slow and complex and not received very well. People want simplicity. This is perhaps deja vu for many of you and it also reflects the development from Mach to L4 kernels which only supports synchronous IPC. What do you think (question is in the title)?
Another example, we send data to some kind of interface, it is slow like RS232 for example. Here we have use of the benefits of asynchronous IPC, serialization and non blocking send. However, since the interface is slow we can send much faster than the interface can send on its end. Now we have two possibilities, to discard data or stall until the interface is ready to accept more data. I think most of the time we don't want to lose any data so we must wait. In practice on the interface driver end, you probably have implemented this with two threads if we only have synchronous IPC. One sending thread and one thread accepting data which puts the data in a buffer. Using two threads gives us almost non blocking send (still we have task switch but the blocking is short). When the buffer is full, the buffer thread simply don't go into receive state preventing the rendevouz. Now we have implemented flow control in simple way. This is of course possible with asynchronous IPC as well, either by waiting for a reply from the interface thread or having some kind of blocking mechanism in the kernel when the message pool is full. Blocking when the message pool is full is much less trivial than the rendevouz block.
So in practice asynchronous IPC doesn't help us in that much in real scenarios and might rather discourage us from using the parallelism provided by modern CPUs. You often fall into the trap of serialization using asynchronous IPC. Also asynchronous IPC require more involvement from the kernel when in comes to message pool management and states it must support. The benefit of asynchronous IPC is less task switching but as you could see with the second example, we often don't get rid of it anyway.
Having asynchronous IPC adds to the complexity a lot and also we have to support more different scenarios that can happen with asynchronous IPC, the complexity just increases for very little benefit. My kernel supports both asynchronous and synchronous IPC but I'm starting to wonder if supporting asynchronous IPC is really worth the effort. It requires much more code and involvement from the kernel and adding security to it just makes even more complex. Mach kernel is a good example of this where the IPC was slow and complex and not received very well. People want simplicity. This is perhaps deja vu for many of you and it also reflects the development from Mach to L4 kernels which only supports synchronous IPC. What do you think (question is in the title)?