21 ms·
How to receive a million packets per second
- deleted 11y ago[deleted]
- edude03 11y agoHmm, I might be missing something here, but don't most high performance network applications skip the kernel for this exact reason? (IE http://highscalability.com/blog/2014/2/13/snabb-switch-skip-the-os-and-get-40-million-requests-per-sec.html http://highscalability.com/blog/2014/2/13/snabb-switch-skip-...) Makes me wonder how often bypassing the kernel is used in production networked applications.
- kev009 11y agoIt's built into FreeBSD: https://www.freebsd.org/cgi/man.cgi?query=netmap&sektion=4 https://www.freebsd.org/cgi/man.cgi?query=netmap&sektion=4 Netmap is commonly used in HFT as well as packet filtering applications. I believe Verisign is running some of the root DNS servers with netmap as well, getting millions of connections per second.
- bobmagoo 11y agoYeah it is, Robert Graham gave a great talk about it over at https://www.youtube.com/watch?v=D09jdbS6oSI https://www.youtube.com/watch?v=D09jdbS6oSI with a writeup at http://c10m.robertgraham.com/2013/02/c10m-in-1990s.html http://c10m.robertgraham.com/2013/02/c10m-in-1990s.html
- sj4nz 11y agoThere is a project "Kerlnel" http://kerlnel.org/ http://kerlnel.org/ that is supposed to be Erlang instance running on bare metal. Site appears to be down and the Github https://github.com/kerlnel https://github.com/kerlnel hasn't been touched since 2013. Then there is http://erlangonxen.org/ http://erlangonxen.org/ which puts Erlang on top of Xen instead of another operating system.
- easytiger 11y agoWell he should have compared this with onload enabled. He was using a solarflare after all. Limited benefits on mc compared with TCP though.
- pjc50 11y agoHe's "cheating" by using sendmmsg() to send many messages per system call, reducing the number of context switches.
- amluto 11y agoBarely. On a reasonably configured kernel (you need both syscall auditing and context tracking turned off, which is doable at compile time or runtime), a modern CPU should be able to round-trip a syscall in under 40 ns. That only eats 4% CPU at 1M syscalls per second. (It's slightly worse than that due to extra cache and TLB pressure, but I doubt that matters in this workload.)
- scurvy 11y agoLots of High Frequency Trading (HFT) applications use an userland based IP stack.
- jedberg 11y agoA joke answer and a serious question: A: "Use BSD" Q: Why is there such a strong focus on trying to get Linux network performance when (I think) everyone agrees BSD is better at networking? What does Linux offer beyond the network that BSD doesn't when it comes to applications that demand the fastest networks? ps. I think the markdown filter is broken, I can't make a literal asterisk with a backslash. Anyone know how HN lets you make an inline asterisk?
- majke 11y agoI have no idea. How many UDP packets can FreeBSD pass to application? I don't think there is any particular problem with Linux. The core problem of "slow" performance is mostly due to limitations of BSD API (recvmmsg is a good example of a workaround), and due to the feature richness of Linux. Also, doing the math: 2GHz / 350k pps = 5714 cycles per packet. 6k cycles to deliver the packet from NIC to one core, then pass it between cores and copy over to application. That ain't bad really.
- jgrahamc 11y agoMarkdown? This is HN where we use whatever PG* decides we're allowed to use. https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc *Paul Graham
- jedberg 11y agoSo in other words it's impossible to have two inline asterisks without a space after the first one. Oh well.
- elevensies 11y ago**
- jedberg 11y agoYou indented, which means there is no formatting at all. You cheated. :)
- netman 11y agoThe Automattic guys did some testing a few years ago with better results on SolarFlare. I wonder where their testing ultimately ended up. https://wpneteng.wordpress.com/2013/12/21/10g-nic-testing/ https://wpneteng.wordpress.com/2013/12/21/10g-nic-testing/
- chx 11y agoPerhaps because I am not really a low level programmer it strikes me odd that "receive packet" is a call. I would expect to pass a function pointer to the driver and be called with the packet address every time one has arrived.
- colanderman 11y agoFor your own sanity, you want some control over which thread is processing a packet, and at what point it does so. The easiest way to do this is to explicitly notify the kernel when you are in fact interested in another packet, and whether you wish your thread of control to be suspended until such a packet arrives if there is no next packet. The JavaScript model of "call some callback when the currently-executing function returns" doesn't work, because C is not event-based. The embedded model of "interrupt whatever's happening and invoke some handler on the current thread of control" is just an absolute nightmare to deal with.
- jerf 11y ago"The JavaScript model of "call some callback when the currently-executing function returns" doesn't work," I can't prove it, but at this scale, I am guessing that the cost of constructing call frames to call into the callback will start to matter, too. Switching into an already-existing context is probably significantly cheaper. (Well, it's definitely significantly cheaper to switch into an existing C context than construct a Javascript call, but, that's sort of cheating. Or a low blow. Or something like that.)
- deleted 11y ago[deleted]
- TickleSteve 11y agoNot even remotely... To setup for a call to a C function is a matter of a handfull of instructions. To setup a context switch is hundreds.
- 11y ago
- samstave 11y agoI was curious to see how many pps our servers are handling... We have an app server that currently handles 40K concurrent users per node. I get ~63pps only: TX eth0: 42780 pkts/s RX eth0: 64676 pkts/s TX eth0: 41570 pkts/s RX eth0: 63401 pkts/s TX eth0: 41867 pkts/s RX eth0: 63697 pkts/s TX eth0: 41585 pkts/s RX eth0: 63187 pkts/s TX eth0: 40408 pkts/s RX eth0: 61912 pkts/s TX eth0: 41445 pkts/s RX eth0: 63299 pkts/s TX eth0: 41119 pkts/s RX eth0: 63186 pkts/s TX eth0: 41502 pkts/s RX eth0: 63153 pkts/s TX eth0: 40465 pkts/s RX eth0: 62118 pkts/s TX eth0: 42105 pkts/s RX eth0: 63986 pkts/s But this is utilizing 7 of 8 cores on each node... with CPU util very low.
- zurn 11y agoWhere does the funny 50 kpps per core idea in the lead-in come from? This would mean falling far short of 1 gigE line rate with 1500 byte packets! This is is trivially disproven with everyday experience of anyone who's run scp over his home lan or crossover cable?
- majke 11y agoTCP != UDP. In TCP recv() gives you a buffer. In UDP recv() gives you a packet. Good luck receiving 50k pps of UDP packets, doing some processing and _sending_ 50k pps responses back. It actually is hard.
- zurn 11y agoThe lead-in wasn't talking about UDP. And the article is specifically showing you how to use the multiple-packets-per call APIs (sendmmsg et al) and hitting 350 kpps with simeple single-threaded code and UDP. Then 1.4 Mpps with tuning and parallelism. And even if you were using the slow API, even with ping: [7 year old desktop]$ sudo ping -q -f -c 100000 localhost PING localhost.localdomain (127.0.0.1) 56(84) bytes of data. --- localhost.localdomain ping statistics --- 100000 packets transmitted, 100000 received, 0% packet loss, time 954ms rtt min/avg/max/mdev = 0.004/0.004/0.195/0.002 ms, ipg/ewma 0.009/0.005 ms Google around for some iperf or netperf results that people are generally getting with Linux.
- shin_lao 11y agoIt's an interesting post. If you really want to squeeze out all the performance of your network card, what you should use is something like DPDK. http://dpdk.org/ http://dpdk.org/
- LinuXY 11y agoRight- Though the point of the post was to dispel the fallacy that the Linux kernel can only handle 50k pp/s per core. Using RDMA effectively bypasses the kernel. He's also testing with a SolarFlare card which doesn't support DPDK, though it does support RDMA with OpenOnload. What I've found is that RDMA is the "easy" part to get right, as it's fairly simple. Not every network card is created equal with respect to how many packets it can actually pass through to the kernel however, partially in part to the kernel driver (whether it's using NAPI or not, driver efficiency, MSI-X support, interrupt coalescing) and the card itself (onboard buffer, latency characteristics, etc.) 10g cards max out at around 14Mpp/s @ 60 bytes when the kernel is involved and everything is perfectly tuned. Which should be where the card he's using falls. A generic onboard Intel card generally maxes out around 8-10Mpp/s. But both would most likely be able to hit 16Mpp/s @ 60 bytes if using RDMA in any form.
- deleted 11y ago[deleted]
- shin_lao 11y agoDPDK is great because it means telling to the customer "you keep your network, just buy a server with this card and we promise you unreal throughput". If you really want maximum throughput with RDMA, I think the best is to go InfiniBand.
- Galanwe 11y ago...Except it's dead. InfiniBand was the way to go 5/10 years ago, when 10G Ethernet was not there. Nowadays, most of companies that invested in IB years ago are stuck with a dead infrastructure. It costs a lot, there is very little knowledge about the techno, and most support for it is dropping (e.g. glusterfs). Sad truth is most of these old IB infra are now used for IPoIB ... Source: been working in HFT firms implementing IB RDMA, then GBEth RDMA, now proprietary NIC RDMA
- deleted 11y ago[deleted]
- kpennell 11y agopost test
- bitL 11y agoExcellent article! Thanks for sharing! I am glad to learn something new today! ;-)
- adekok 11y agoNice, except recvmmsg() is broken. http://man7.org/linux/man-pages/man2/recvmmsg.2.html http://man7.org/linux/man-pages/man2/recvmmsg.2.html The timeout argument does not work as intended. The timeout is checked only after the receipt of each datagram, so that if up to vlen-1 datagrams are received before the timeout expires, but then no further datagrams are received, the call will block forever. Which makes it useless for any application that wants to service data in a short time frame. The only way around it is to use a "self clocking" method. If you want to receive packets at least every 10ms, set a 10ms timeout... and then be sure to send yourself a packet every 10ms. I've done similar tests with UDP applications. It's possible to get 500K pps on a multi-core system with a test application that isn't too complex, or uses too many tricks. The problem is that the system spends 80% to 90% of its time in the kernel doing IO. So you have no time left to run your application. Another alternative is pcap and PF_RING, as seen here: https://github.com/robertdavidgraham/robdns https://github.com/robertdavidgraham/robdns That might be useful. Previous discussion on robdns: https://news.ycombinator.com/item?id=8802425 https://news.ycombinator.com/item?id=8802425
- justincormack 11y agoThe Snabb switch paralkelisation experiments are getting to 35 million packets per second doing real work (encap decap) in Linux userspace[1] [1] https://groups.google.com/forum/m/#!topic/snabb-devel/_vKQgCU29_Q https://groups.google.com/forum/m/#!topic/snabb-devel/_vKQgC...
- ajross 11y agoTunnel encapsulation is real work, but not all real work can be mapped to tunnel encapsulation. The point of all that work to context switch into processes to handle small amounts of network I/O is that very often THE CORRECT SOFTWARE ARCHITECTURE is for multiple address-space-separated processes to be doing small amounts of network I/O. That I/O "means something" to a larger data model being implemented by the software. It's true that for some tasks that "look like routing" there's no point to having that kind of external data model. The packets are the data being operated on. So there's little value in process separation and you might as well DMA them all streamwise into a single process to do it. And that's great stuff, but AFAICT it's really not what the linked article is about. Ultimately, all those packets are going to end up in conventional processes, because that's where conventional processing needs to happen. There are very good reasons why we like our page-protected address space separation in this world!
- brobinson 11y agoWhy even have netfilter ("iptables") loaded in the kernel at all? Won't those two rules still have to be evaluated for each packet even if the rules are saying not to do anything? There are additional things at play here, too, including what the NIC driver's strategy for interrupt generation is and how interrupts are balanced across the available cores, whether there are cores dedicated to interrupt handling and otherwise isolated from the I/O scheduler, various sysctl settings, etc. There's further gains here if you want to get really into it.
- floridaguy01 11y agoYou know what is cooler than 1 million packets per second? 1 billion packets per second.
- known 11y agoman ethtool
- danpalmer 11y ago> Last week during a casual conversation I overheard a colleague saying: "The Linux network stack is slow! You can't expect it to do more than 50 thousand packets per second per core!" > They both have two six core 2GHz Xeon processors. With hyperthreading (HT) enabled that counts to 24 processors on each box. 24 * 50,000 = 1,200,000 > we had shown that it is technically possible to receive 1Mpps on a Linux machine So the original proposition was correct.
- digital-rubber 11y ago+1 for Dan Palmer (if i had points i'd give them). Anybody btw know easy way to avoid seeing cloudflare.com from the main page?
- Anderkent 11y agoAFAIK he's only using 4 out of the 24 cores: > two cores busy with handling RX queues, and third running the application, it's possible to get ~650k pps That's ~200k pps per core, so 4x the initial bet.
- feld 11y agognn has done a lot of research on *nix networking and the conclusion is "single sockets are always faster than multiple sockets". There's a huge performance hit when trying to process packets as fast as possible and you throw NUMA into the mix. Remote memory is accessed more slowly, and pinning work to specific CPUs is non-trivial.
- nikropht 11y agoActually the Linux kernel is rather fast if used right. The Mikrotik CCR1036 series routers have a 36 core tile CPU with each core running at 1.2ghz it can cram out 15 million pps. https://www.youtube.com/watch?v=UNwxAjJ4V4A https://www.youtube.com/watch?v=UNwxAjJ4V4A RouterOS is based on the Linux kernel see https://en.wikipedia.org/wiki/MikroTik https://en.wikipedia.org/wiki/MikroTik