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/
Related
I'm using TUNCTL with {active, true} to get UDP packets from a TUN interface. The process gets the packets and sends them to a different process that does work and sends them to yet another process that pushes them out a different interface using gen_udp. The same process repeats in the opposite direction, I use gen_udp to get packets and send them to a TUN interface.
I start seeing overruns on the incoming TUN interface when CPU load is close to 50%, about 2500 packets/sec. I don't loose any packets on gen_udp side ever, only with tunctl. Why is my application not getting all the packets from the TUN interface when CPU is not overloaded? My process has no messages in it's message queue.
I've played with process priorities and buffer sizes, which didn't do much. Total CPU load makes a bit of a difference. I managed to lower CPU load, but even though I saw a slight increase in TUN interface throughput, it now seems to max out at a lower CPU load, say 50% instead of 60%.
Is TUNCTL/Procket not able to read packets fast enough or is TUNCTL/Procket not getting enough CPU time for some reason? My theory is that Erlang Scheduler doesn't know how much time it needs as it's calling a NIF and it doesn't know about the number of unhandled messages on the TUN interface. Do I need to get my hands dirty with C++ and/or write my own NIF? MSANTOS HELP!
As expected, it was a problem with TUNCTL not getting enough CPU time when active is true. I used procket:read which gets the packet from the TUN buffer. Using this approach lets you specify how often to check the buffer, which tells Erlang Scheduler how much time your process needs. This let me load the CPU up to 100% if needed and allowed me to get all the packets from TUN interface that I needed. Bottleneck solved.
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.
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.
I typically use hardwired serial port connections between embedded devices for custom command/response/status protocols.
In this application I plan to use the microchip TCP/IP stack and Wi-Fi module with no OS to exchange short (<= 100 byte) commands and responses.
The stack is up and running on a microchip ethernet development kit and I am able to ping it from my desktop (not using the Wi-Fi module just yet).
I suppose I could hack into ping (microchip provides the c source for the stack) and add the messages I need to it, but I am looking for the correct/simplest/best method.
Correct / simplest / best aren't necessarily the same thing. But if I were you, I would consider using UDP instead of TCP.
UDP is a datagram protocol; TCP is stream-oriented and has a lot more overhead (and benefits that come with the overhead). But UDP more closely matches the current serial port byte-oriented (packet-oriented) approach you have today.
Chances are you have some higher-level protocol that receives/buffers/checksums/delimits/parses the data stream you receive from the UART. If you use UDP, you can mimic this nicely with a lean, lightweight UDP implementation. With UDP you just shoot out the bytes (packets) & cross your fingers that they got to the other end (a lot like serial).
TCP is heavier-weight connection-based protocol with built-in resending, acknowledgments, in-order delivery, timers, back-off algorithms, etc. On most embedded systems I've worked with using TCP (several different stacks), UDP is lighter-weight & outperforms TCP in terms of code size & throughput.
Also don't forget that TCP is used as the backbone of the internet; some packets pass through a dozen or more hops (routers/gateways) en route to the final destination. Lots of places for packets to get dropped, so TCP handles a lot of messy details transparently. I'd guess in your system/situation, we're talking about a LAN (everyone on the same wire) and transmission will be pretty reliable... thus the TCP overhead isn't really necessary.
There are times when the benefits of TCP justify the overhead, but from what you've written I think you should consider a basic UDP datagram set up. Just google "simple udp example" and you'll see the basic structure. For example, here is a simple UDP client/server example using just 43 lines (server) and 30 lines (client).
When you have a TCP/IP stack, it should provide a send() function to send some data messages.
Some small devices come only with a simple UDP/IP implementation, since this is a lot simpler. If you don't need the sequence control and reliability of TCP you could consider to use UDP to send short messages. This is much better to hack the ICMP messages.
But if you need the comfort and reliabilty of the TCP stream protocol, dont re-invent this on base of IUDP. Usually you can't do it better, more efficient and with less effort.
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.