Skip to content

Instantly share code, notes, and snippets.

@piscisaureus
Last active January 22, 2020 22:20
Show Gist options
  • Save piscisaureus/7ca55b153a1b3f8085c6ae49c4e6c837 to your computer and use it in GitHub Desktop.
Save piscisaureus/7ca55b153a1b3f8085c6ae49c4e6c837 to your computer and use it in GitHub Desktop.
So here's the things to consider:
* Do not preallocate a read buffer per socket.
Either use polling or use a shared buffer pool.
* Avoid statefulnews, e.g:
- In windows, you can't use multiple completion ports with a handle.
- On unix, a socket is either in blocking or non-blocking mode
This creates problems when you want to share a handle with other processes
or between threads. For example, you might want to switch stdout to
non-blocking, but if stdout was inherited and shared with the parent
process, the parent process might not expect this and crash or malfunction.
For that reason, libuv implements separate code paths for shared handles,
which more than doubles the code size.
* Consider that not all protocols have TCP-like semantics. Consider:
- Some protocols (anything SOCK_SEQPACKET and also websockets and windows
named pipes in certain modes) are message-oriented. UDP packets are also
essentially messages. This needs to be a consideration when considering
the API.
- Some protocols do not support graceful close. TTY stdin might report an
EOF marker (zero size read) and yet more data follows after that.
Named pipes don't support graceful close at all. Unix FIFOs are half
duplex.
* For random access devices (files/block devices), avoid relying on the
operating for keeping track of the read position. This creates problems
when multiple threads are involved. E.g. when you offload the actual
file write to a thread pool, writes may happen in a different order than
in which they were submitted, which causes data corruption.
OS X had a bug for many years where the file position was entirely
un-thread-safe and files would get randomly corrupted in seemingly unrelated
locations.
Instead, prefer pread/pwrite for files. Windows has similar functionality.
* Consider that certain devices expect page-aligned buffers. Typically this
is true for block devices and files that are opened in unbufferd mode.
* Some third-party libraries (e.g. c-ares and libcurl) expect that you can do
unix-style poll/select on sockets for them. So you need to support this even
if you have a more efficient mode available for internal use.
(This is essentially the reason the wepoll strategy was developed).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment