Hi all.. I have run into this as well. One of my products uses 10GBaseT ethernet, and is often hobbled when moving data. I don’t have a good solution to offer for performance, but this is what I have come up with.
- Sockets and NSObjects perform an awful lot of memcpy’s. (Unnecessary copying memory can be one huge waste of time..) - There is no way to shortcut any stream/socket reads by providing a dedicated buffer. (i.e.: like a “PF_Ring" style ring buffer) The way that I have improved this was to use GCDAsyncSocket, and then to provide my own subclass of NSMutableData. This required me to hack the GCDAsyncSocket code to switch between a traditional NSMutableData object, and my own. The solution worked pretty nicely. I was able to moderately reduce the number of memcpy’s, which in turn, picked up performance. In my mind, the best solution is to create a pin-able piece of memory that can’t be paged out, and then have the networking stack “read/stream” functions write directly into it. I have considered writing a Network Kernel Extension, which would essential provide the functionality of PF_RING.. (This exists in Linux.) But it would involve a new set of skills.. :) Curious to hear what others have done to pick up performance. bob.. > On Sep 11, 2015, at 06:15, Jens Alfke <j...@mooseyard.com> wrote: > > GCDAsyncSocket has an interesting approach, where you can tell it what you > want to read, like a certain number of bytes, or everything up to a specific > byte sequence (like CRLF), and it'll call you back when it's read it. > > Another approach would be to use synchronous I/O calls, of course, but Cocoa > APIs don't make that easy to do. > > —Jens > >> On Sep 10, 2015, at 6:12 PM, Adam Kaplan <adk...@gmail.com> wrote: >> >> It’s amazing how many times we solve this same problem over-and-over. It’s >> so difficult because every case is slightly nuanced :( >> >> I agree with everything Jens said, as usual. A ring buffer is fastest, but >> if your max message size is unknown and you can’t do stream-style parsing, >> they’ll always be some nasty edge cases… >> >> Just feeding into an NSMutableData is a good approach too and probably the >> most common. There are some downsides, such as multi-threaded parsing >> complexity and manually having to manage the addition and removal of data >> blocks. >> >> A third tool in the arsenal is GCDs dispatch_data_t, which is very well >> suited for combining, traversing and removing arbitrarily-sized data blocks >> in a multi-threaded streaming environment. The downsides there are GCD's >> boilerplate overhead and a performance profile that is not always easy to >> reason about. >> >> — adam >> >> >>> On Wednesday, September 9, 2015 at 6:30 PM, Jens Alfke wrote: >>> >>> >>>> On Sep 9, 2015, at 2:07 PM, Motti Shneor <su...@bezeqint.net >>>> (mailto:su...@bezeqint.net)> wrote: >>>> I need reading messages off the stream, each prefixed by 4 bytes >>>> containing its size. I was wondering if it was advisable to first read >>>> just the size (4 bytes) then read the rest of the message, or maybe it was >>>> better to have a big buffer into which to “drain” the stream, then parse >>>> my messages off the buffer? >>> >>> The first approach won’t work, because the amount of data received is >>> unpredictable. For instance you might receive only three bytes, which isn’t >>> enough to parse the data size. Or you might be able to read the data size, >>> but then try to read a 100000-byte message and get only 1500 bytes of it. >>> >>> The usual approach when parsing data asynchronously from a network stream >>> is to keep a variable-size buffer of unparsed data. When data arrives, you >>> read all of it and append it to the buffer; then you try to parse the data >>> in the buffer. If there’s not enough to parse yet, you give up till there’s >>> more; or if you parse some data, you remove it from the start of the buffer. >>> >>> So in your case you’d first check whether the buffer has at least four >>> bytes; if so, you look at the length, and check whether that many more >>> bytes are available. If they are, you read the whole message and remove it >>> from the buffer. >>> >>> An NSMutableData object works well as a buffer, if you’re not too concerned >>> about high performance. The fastest implementation is probably some sort of >>> custom ring buffer. >>> >>> —Jens >>> _______________________________________________ >>> Do not post admin requests to the list. They will be ignored. >>> Macnetworkprog mailing list (Macnetworkprog@lists.apple.com >>> (mailto:Macnetworkprog@lists.apple.com)) >>> Help/Unsubscribe/Update your Subscription: >>> https://lists.apple.com/mailman/options/macnetworkprog/adkapx%40gmail.com >>> >>> This email sent to adk...@gmail.com (mailto:adk...@gmail.com) >> >> > > _______________________________________________ > Do not post admin requests to the list. They will be ignored. > Macnetworkprog mailing list (Macnetworkprog@lists.apple.com) > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/macnetworkprog/bob%40gluetools.com > > This email sent to b...@gluetools.com _______________________________________________ Do not post admin requests to the list. They will be ignored. Macnetworkprog mailing list (Macnetworkprog@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/macnetworkprog/archive%40mail-archive.com This email sent to arch...@mail-archive.com