0

I have IOCP application that stores a 64kb buffer per socket context. It uses lot of RAM, while handling thousands of sockets. Instead of this i want to switch to model where I have a 64kb buffer per iocp-thread context (like i can do it in epoll and kqueue). For this i need my completion port be able to receive notifications without bytes copying to the provided WSABUF and after notification simply call async WSARecvFrom(without providing overlapped structure,i'm using udp for tests) until i receive WSAEWOULDBLOCK. I've read that following technique can be achieved if i provide empty WSABUF (buf = NULL, len =0) for the WSARecvFrom call with overlapped structure. But it doesn't work: IOCP never "wakes up" as buffer is too small.

Are there other ways i can make such scenario possible?

user1266334
  • 153
  • 2
  • 12

1 Answers1

2

This works fine for TCP and it's a good way of avoiding the "locked pages" limit which was a big problem on earlier versions of windows but seems to be less of an issue now. It should work just fine for your situation.

I have a set of IOCP example code which can be downloaded from here and this supports "zero byte reads" and subsequent async reads (that is it only issued an overlapped read with a buffer once a read with a zero byte buffer completes), my latest code supports both sync and async reads after zero byte read completion.

Note that if you're dealing with TCP, you mention that you're using UDP "for tests", then you can achieve the "single buffer" by only issuing a single overlapped read per connection. Once that read completes you can then deal with it before issuing a new overlapped read using the same buffer...

The "zero byte read" is still useful if you need to deal with many thousands of concurrent connections where the connections send data infrequently as it reduces the number of pages locked at one time to the minimum. Using it to reduce memory usage would require that you only allocate a buffer for the connection once a "zero byte read" has completed.

Len Holgate
  • 21,282
  • 4
  • 45
  • 92
  • Thank you for reply. But what about UDP? My application handles both TCP and UDP connections and i want to have a single architecture. Is it possible for UDP? – user1266334 May 18 '12 at 07:34
  • I've not tried with UDP. I expect that the I/O will complete with a "more data" error and you will be unable to obtain the rest of the datagram. Are you really expecting UDP datagrams of 64K? I assume you're not going across any routers and this is a direct local connection? – Len Holgate May 18 '12 at 11:34
  • I/O never completes for "zero byte read". If i put 1-byte buffer, it's also never completing. However if i put 64k buffer it works fine. Maximum UDP datagram size is 64k, so yes i'm expecting such datagrams. I'm making tests on localhost, but my application of course will work in internet – user1266334 May 18 '12 at 13:23
  • Strange that it never completes, though I have seen other "issues" with IOCP and UDP (though only when FILE_SKIP_COMPLETION_PORT_ON_SUCCESS is enabled (see http://www.lenholgate.com/blog/2010/01/file-skip-completion-port-on-success-and-datagram-socket-read-errors.html). IMHO you would be advised to read this: http://stackoverflow.com/questions/10355626/udp-packet-size-and-packet-losses regarding sending large UDP datagrams over the internet. I expect that you are likely to find such large datagrams very unreliable due to packet loss. – Len Holgate May 18 '12 at 16:09
  • 1
    libuv appears to do zero-byte receives on UDP sockets. Their trick is to use the `MSG_PEEK` flag so that the zero-byte receive doesn't consume the waiting packet. – Nathaniel J. Smith Feb 03 '17 at 07:37