The only possible reason that I could think of is the low overhead ie fixed header size of only 2 bytes minimum, leading to low packet size. Are there other factors in the design of the protocol?
EDIT:- I am sorry, I made a mental typo (?), as #Shashi pointed out, I actually meant high latency, low bandwidth.
MQTT is designed for devices with little memory footprint, low network bandwidth etc. Devices, for example sensors, energy meters, pace makers etc are ideal use cases for MQTT. Low latency means high speed. For low latency you require different protocol, like Reliable Multicast running over Gigabit Ethernet or InfiniBand networks.
One of the key factors is, that the TCP connection a MQTT client establishes is reused all the time. That means you don't have to establish a new connection all the time as it's the case with classic HTTP. Also, as you already suspected, the very low packet size is key here, typical MQTT messages don't have much overhead over the raw TCP packet.
To save more bandwidth on unreliable networks, the persistent session feature of MQTT allows clients to subscribe only once and on reconnect the subscriptions are retained for the client. For subscribing clients this can drastically reduce the overhead as the subscription message is only sent once.
Another reason, it seems is the Last Will and Testament feature, which is a useful to have feature in high latency network, low bandwidth and unreliable networks.
Related
I got asked in an interview recently to design a file upload feature. After the initial discussion, The interviewer asked if I can design for multiple threads. My thought was, As the network bandwidth is limited and the internet is connected through a serial data connection, the network bottleneck will kick-in much before the CPU bottleneck, and a multiple thread implementation would have a limited performance improvement. But the interviewer was hell bend on the multi-thread approach. What are the arguments in favor of a multi-thread upload approach? (I recently came to know that AWS has a library which permits uploads on multiple threads. So there should be some advantages I am unaware of.)
A TCP connection can be limited in rate even on a high-speed network because of the bandwidth delay product.
A high bandwidth-delay product is an important problem case in the design of protocols such as Transmission Control Protocol (TCP) in respect of TCP tuning, because the protocol can only achieve optimum throughput if a sender sends a sufficiently large quantity of data before being required to stop and wait until a confirming message is received from the receiver, acknowledging successful receipt of that data. If the quantity of data sent is insufficient compared with the bandwidth-delay product, then the link is not being kept busy and the protocol is operating below peak efficiency for the link.
One easy way to work around TCP limitations on connections with large bandwith delay products is to do multiple streams in parallel.
According to my knowledge, UDP does not use the path MTU to avoid fragmentation which however TCP does. I am trying to come up a reason to this particular design.
TCP needs to avoid fragmentation because it has to retransmit the whole datagram even if just one fragment is dropped. On the contrary, UDP does not need to retransmit datagram, it's up to the application layer to ensure the integrity.
In conclusion, fragment will slow the TCP transport protocol but not UDP transport protocol.
Here comes the problem, for communication that need integrity, whether employ TCP which natrually guarantee the integrity, or develop an application layer retransmit protocol upon UDP, it will need to resend the whole datagram if not ACKed. Then, fragmentation will slow down application layer retransmit protocol upon UDP just the same as TCP.
What's wrong with my reasoning?
UDP is a datagram protocol where each packet means a single entity, independent of the other packets (UDP does not detected duplication, reordering etc). TCP instead is a stream protocol, that is the whole transfer consists of a single unstructured octet stream similar to a large file. To make the transfer of this stream more efficient it makes sense to detect the MTU of the connection and try to send mostly packets which max out this MTU, thus reducing the overhead of the transfer. To further reduce the overhead TCP will merge multiple consecutive writes into as few packets (with max MTU) as possible.
UDP instead can not avoid fragmentation by itself because it transmits the datagram as it is, that is datagram boundary is determined by packet boundary. Any kinds of optimization to reduce overhead have to be done by the application itself.
Thus TCP is best suited for applications where its features like guaranteed and ordered delivery and efficient use of bandwidth are needed. Unfortunately these features come with drawbacks like comparable slow connection setup, higher latency (in case of packet loss) etc. But there are applications which don't need all the good parts but have to avoid the bad parts. For example real time audio and video can deal with packet loss but needs a low latency, i.e. it does not matter if all data arrive but they have to arrive fast. In these cases the more simple UDP protocol is better suited.
Because there's nothing useful it can do with the MTU. It's a datagram protocol.
Because there is no path. It's an connectionless protocol.
What's the rationale behind making USB a polling mechanism rather than interrupt-driven? The answers I can come up with some reasoning are:
Leave control of processing efficiency and granularity to OS, rather than the device itself.
Prevent "interrupt storms" by faulty devices.
Some explanations on the net that I found say that it's mostly because of the nature of USB devices. They are mostly microcontroller-based systems which cannot queue larger transfers therefore require short interrupt intervals and such short interrupt intervals may not be the most efficient. Is that true?
Could there be other reasons?
The overarching premise of the development of USB was, "cheap chips". This was done, through the use of polling, which reduces the need for a higher arbitration protocol.
Firewire, which did allow for interrupts from the devices and even DMA, was much more expensive. So USB won in the low-cost field, and firewire in low-latency/low-overhead/... field. Due to history USB more or less won.
What's the rationale behind making USB a polling mechanism rather than interrupt-driven?
This seems to be anti-USB FUD (as in Fear-Uncertainy-Doubt).
The reason is that this simplifies things on the harware level quite a bit - no more collisions for example. USB is half-duplex to reducex the amount of wires in the cable, so only one can talk anyway.
While USB uses polling on the wire, once you use it in software you will notice that you have interrupts in USB. The only issue is a slight increase in latency - neglible in most use cases. Since the polling is usually realized in hardware IIRC, software only gets notified if there is new data.
On the software level, there are so-called "interrupt endpoints" - and guess what, every HID device uses them: Mice, Keyboard and Josticks are HID.
There are three ways to avoid data transfer collisions on a bus:
Have a somewhat complex bus management protocol. Such a protocol has to be rather sophisticated, as when too simple, it will make the bus rather slow (see Token Ring, which is rather simple, yet inefficient). However, having a sophisticated protocol makes all components expensive as all of them require management logic and need to understand of how the bus actually works (see Firewire).
Don't avoid them at all, allow them but detect and handle them. This is also somewhat complex and the bus cannot guarantee any speed or latency as if there are constantly collisions, throughput will fall and latency will raise (see Ethernet without switches, see WiFi).
Have one bus master that controls who can use the bus at which time and for how long. This is inexpensive, as only the master must be sophisticated and the master can give any possible guarantee regarding speed or latency.
And (3) is how USB works and not even the master USB chips need to be sophisticated as the master is usually a computer with a fast CPU and can perform all bus management in software.
USB device chips are dump as toast. They don't need to understand the nifty details of the bus. They just have to look for packets addressed to them which are either control packets, e.g. requesting meta data or selecting a configuration, data packets sent by the master, or poll requests from the master saying "if you have something to send, the bus is now yours".
To make sure the master polls them on time, they hand out a simple description table on request, that explains which endpoints they offer, how often those need to be polled, and how much data they will at most transfer when being polled. The master can use that information to build up a poll schedule that ensures that all devices are polled on time and get the bus for long enough to allow their maximum transfer size. Of course, this is not possible under all circumstances. If you connect too many devices that require very frequent polling and always want to send a lot of data, your system may refuse to add a new device with the error, that its poll requirements cannot be satisfied anymore. Yet that situation is rare in practice and USB is limited to 127 devices (hubs count as devices, so does the master itself).
Power management works in a similar way. Every device tells the master how much power it needs and the master ensures that the bus can still deliver that much, taking active hubs into account. If you connect another device and the bus cannot power it anymore, adding the device will fail with an error.
This allows a fairly complex, powerful, and fast bus system, yet with components that don't even need a real CPU. The simplest USB chips out there are just bridges to a serial data line (like an internal RS-232 bus or an I2C bus) and there is nothing really configurable and they cannot run software or have a firmware one could update. They just place incoming data packets into a buffer and then sent the buffer content bit for bit over the serial bus and they receive serial data in another buffer and return the buffer content when being polled. As for telling the master the configuration (including device and vendor IDs, as well as human readable strings), they simply send the content of a small external EPROM. Things cannot get much simpler than that yet such a chip is enough to build plenty of USB hardware already.
Does UDP send all packets as soon as they become available as opposed to TCP's monitored approach?
Thanks.
TCP has congestion control, UDP does not as it is connection-less.
But your question covers multiple issues: does sending a message cause it to be immediately delivered? Not always, on high performance networking hardware you will find Interrupt Coalescing which causes the operating system to delay passing messages to the hardware in order to optimise high throughput situations. Some further explanation here:
http://blogs.informatica.com/perspectives/index.php/2009/06/10/how-does-interrupt-coalescing-affect-low-latency-high-performance-messaging/
we have an application requirement where we'll be receiving messages from around 5-10 clients at a rate of 500KB/sec and doing some internal logic then distrubuting the received messages among 30-35 other network entities.
What all the tcp level or thread level optimizations are suggested ?
Sometimes programmers can "shoot themselves in the foot". One example is attempting to increase a linux user-space application's socket buffer size with setsockopt/SO_RCVBUF. On recent Linux distributions, this deactivates auto-tuning of the receive window, leading to poorer performance than what would have been seen had we not pulled the trigger.
~4Mbits/sec (8 x 500KB/sec) per TCP connection is well within the capability of well written code without any special optimizations. This assumes, of course, that your target machine's clock rate is measured in GHz and isn't low on RAM.
When you get into the range of 60-80 Mbits/sec per TCP connection, then you begin to hit some bottlenecks that might need profiling and countermeasures.
So to answer your question, unless you're seeing trouble, no TCP or thread optimizations are suggested.